Erstellen einer REST-API mit Node.js und einer Oracle-Datenbank. Teil 2

Teil 2: Erstellen einer REST-API: Datenbankgrundlagen


Im ersten Artikel haben Sie einen Webserver erstellt. Hier erstellen Sie ein Modul, das für das Starten und Herunterfahren des Datenbankverbindungspools mit node-oracledb verantwortlich ist . Fügen Sie eine Funktion hinzu, die die Ausführung einfacher Anweisungen vereinfacht, indem automatisch Verbindungen aus dem Pool abgerufen und freigegeben werden.

Verbindungspool wird ausgeführt


Da node-oracledb auf OCI-Clientbibliotheken basiert, bietet es integrierte Unterstützung für die Erstellung von OCI-Pools, die clientseitig sind und hervorragende Leistungsmerkmale aufweisen. Um einen Verbindungspool zu erstellen, erstellen Sie zunächst eine neue Konfigurationsdatei mit dem Namen database.js im Konfigurationsverzeichnis . Kopieren Sie den folgenden Code, fügen Sie ihn in die Datei ein und speichern Sie die Änderungen.

module.exports = { hrPool: { user: process.env.HR_USER, password: process.env.HR_PASSWORD, connectString: process.env.HR_CONNECTIONSTRING, poolMin: 10, poolMax: 10, poolIncrement: 0 } }; 

Wie bei der Datei config / webserver.js können Sie in dieser Datei einige Eigenschaften mithilfe von Umgebungsvariablen festlegen. Die Verwendung von Umgebungsvariablen bietet Flexibilität bei der Bereitstellung der Anwendung in verschiedenen Umgebungen und hilft beim Speichern von Kennwörtern und anderen vertraulichen Informationen außerhalb des Quellcodes. Führen Sie die folgenden Befehle vom Terminal aus, um die erforderlichen Umgebungsvariablen festzulegen und sicherzustellen, dass sie in zukünftigen Terminalsitzungen verfügbar sind.

 echo "export HR_USER=hr" >> ~/.bashrc echo "export HR_PASSWORD=oracle" >> ~/.bashrc echo "export HR_CONNECTIONSTRING=0.0.0.0/orcl" >> ~/.bashrc source ~/.bashrc 

Möglicherweise stellen Sie fest, dass poolMin und poolMax identisch waren und poolIncrement auf 0 gesetzt wurde. Dadurch wird ein Pool mit fester Größe erstellt, der weniger Verwaltungsressourcen erfordert - eine gute Idee für Pools, die eine konsistente Verwendung erhalten.

Obwohl Node.js häufig als "Single-Threaded" beschrieben wird, steht für bestimmte Vorgänge ein Thread-Pool zur Verfügung, der andernfalls den Haupt-Thread blockieren würde, in dem JavaScript-Code ausgeführt wird. Dieser Thread-Pool wird von node-oracledb verwendet, um alle asynchronen Vorgänge auszuführen, z. B. das Empfangen von Verbindungen und das Ausführen von SQL- und PL / SQL-Code. Die Standardgröße für den Thread-Pool ist jedoch 4. Wenn alle 10 Verbindungen im Pool gleichzeitig funktionieren sollen, müssen Sie die Anzahl der Threads entsprechend erhöhen.

Mit der Umgebungsvariablen UV_THREADPOOL_SIZE kann die Größe des Thread-Pools angepasst werden. UV_THREADPOOL_SIZE kann vor dem Ausführen der Anwendung Node.js oder intern festgelegt werden, muss jedoch festgelegt werden, bevor der erste Aufruf über den Thread-Pool erfolgt. Dies liegt an der Tatsache, dass der Thread-Pool bei seiner ersten Verwendung erstellt wird und nach seiner Erstellung seine Größe festgelegt wird. Öffnen Sie die Datei index.js im Stammverzeichnis der Anwendung und fügen Sie nach der ersten Zeile (die das Webservermodul enthält) die folgenden Zeilen hinzu.

 // *** line that requires services/web-server.js is here *** const dbConfig = require('./config/database.js'); const defaultThreadPoolSize = 4; // Increase thread pool size by poolMax process.env.UV_THREADPOOL_SIZE = dbConfig.hrPool.poolMax + defaultThreadPoolSize; 

Nachdem der Thread-Pool die entsprechende Größe hat, können Sie zum Datenbankmodul wechseln. Erstellen Sie eine neue Datei im Dienstverzeichnis mit dem Namen database.js . Kopieren Sie den folgenden Code, fügen Sie ihn ein und speichern Sie die Änderungen.
 const oracledb = require('oracledb'); const dbConfig = require('../config/database.js'); async function initialize() { const pool = await oracledb.createPool(dbConfig.hrPool); } module.exports.initialize = initialize; 

Dieses Modul führt zuerst Node-Oracle und die Konfigurationsdatei ein. Anschließend wird eine asynchrone Funktion mit dem Namen initialize definiert, die dann über das Objekt module.exports bereitgestellt wird. Die Initialisierungsfunktion erstellt einen Verbindungspool, der als Standardpool im internen Cache der Verbindungspools gespeichert wird.

Jetzt müssen Sie alles verbinden, damit der Verbindungspool gestartet wird, bevor der Webserver geöffnet wird. Gehen Sie zurück zu index.js und fügen Sie die folgende Zeile unter Zeile 1 hinzu.
 // *** line that requires services/web-server.js is here *** const database = require('./services/database.js'); 

Fügen Sie dann der Stratup-Funktion unmittelbar vor dem vorhandenen Try-Block, der den Webserver startet, den folgenden try-Block hinzu.

 try { console.log('Initializing database module'); await database.initialize(); } catch (err) { console.error(err); process.exit(1); // Non-zero failure code } // *** existing try block in startup here *** 

Zu diesem Zeitpunkt können Sie node-oracledb installieren und den Code testen. Führen Sie die folgenden Befehle in einem Terminal aus dem Verzeichnis hr_app aus.

 npm install oracledb -s node . 

Wenn Sie Meldungen sehen, dass das Datenbankmodul und der Webserver ausgeführt werden, herzlichen Glückwunsch - Ihr Verbindungspool funktioniert jetzt!

Verbindungspool herunterfahren


Wenn Sie die Anwendung jetzt schließen (wie zuvor mit Strg + c), wird der Node.js-Prozess zerstört, bevor der Verbindungspool geschlossen wird. Obwohl alle zugehörigen Datenbankprozesse automatisch bereinigt werden sollten, ist es am besten, den Verbindungspool explizit zu schließen, bevor Sie den Node.js.-Prozess beenden.

Kehren Sie zur Datei services / database.js zurück , fügen Sie am Ende die folgenden Codezeilen hinzu und speichern Sie die Aktualisierungen.

 // *** previous code above this line *** async function close() { await oracledb.getPool().close(); } module.exports.close = close; 

Die Funktion close verwendet die Methode oracledb.getPool (), um den Standardpool synchron abzurufen, und ruft dann die Methode close für den Pool auf, um ihn zu schließen.

Um die Schließfunktion zum richtigen Zeitpunkt aufzurufen, fügen Sie der Datei index.js in der Funktion zum Herunterfahren unmittelbar nach dem vorhandenen try-Block, der den Webserver stoppt, die folgenden Codezeilen hinzu .

 // *** existing try-catch block in shutdown here *** try { console.log('Closing database module'); await database.close(); } catch (err) { console.log('Encountered error', e); err = err || e; } 

Wenn Sie die Anwendung erneut starten und schließen, wird das Datenbankmodul nach dem Schließen des Webservers, jedoch vor Abschluss des Vorgangs geschlossen.

Vereinfachen Sie einfache CRUD-Operationen


Das Ausführen von SQL- oder PL / SQL-Code mit node-oracledb erfolgt normalerweise in drei Schritten: Stellen Sie die Verbindung her, führen Sie den Code aus und geben Sie die Verbindung frei. Wenn Sie nur einen Aufruf ausführen möchten (keine mehrstufige Transaktion ist erforderlich), sieht das Empfangen und Freigeben der Verbindung möglicherweise wie Standardcode aus. Ich möchte eine Funktion erstellen, die alle drei Operationen in einem Aufruf ausführt. Kehren Sie zur Datei services / database.js zurück , fügen Sie den folgenden Code hinzu und speichern Sie die Änderungen.

 // *** previous code above this line *** function simpleExecute(statement, binds = [], opts = {}) { return new Promise(async (resolve, reject) => { let conn; opts.outFormat = oracledb.OBJECT; opts.autoCommit = true; try { conn = await oracledb.getConnection(); const result = await conn.execute(statement, binds, opts); resolve(result); } catch (err) { reject(err); } finally { if (conn) { // conn assignment worked, need to close try { await conn.close(); } catch (err) { console.log(err); } } } }); } module.exports.simpleExecute = simpleExecute; 

In der Regel verwenden Sie das Datenbankmodul nicht im Webservermodul, sondern fügen es jetzt hinzu, um zu überprüfen, ob es ordnungsgemäß funktioniert. Öffnen Sie die Datei services / web-server.js und fügen Sie die folgende Zeile unter den vorhandenen Konstantendeklarationen oben hinzu.

 // line that requires ../config/web-server.js here const database = require('./database.js'); 

Verwenden Sie dann den folgenden Code, um den gesamten app.get-Handler zu ersetzen, der mit "Hello World!" Antwortet. (Alle 3 Zeilen).

 // *** line that adds morgan to app here *** app.get('/', async (req, res) => { const result = await database.simpleExecute('select user, systimestamp from dual'); const user = result.rows[0].USER; const date = result.rows[0].SYSTIMESTAMP; res.end(`DB user: ${user}\nDate: ${date}`); }); 

Der neue Handler verwendet die simpleExecute-Funktion des Datenbankmoduls, um die Werte des aktuellen Benutzers und des Systemstempels aus der Datenbank abzurufen. Die Werte werden dann im Vorlagenliteral verwendet, um dem Client mit einer dynamischen Nachricht zu antworten.

Starten Sie die Anwendung erneut und gehen Sie zu localhost: 3000. Sie sollten ungefähr das folgende Bild sehen.

Bild

Wenn Sie diese Meldung sehen, funktioniert alles wie es sollte. Im nächsten Artikel werden Sie die API weiterhin erstellen, indem Sie die Routing-, Controller- und Datenbanklogik für die GET-Anforderung hinzufügen.

Source: https://habr.com/ru/post/de473346/


All Articles