利用 Node.js 实现 SAP Hana 数据库编程接口
為什么80%的碼農都做不了架構師?>>> ??
自 SAP HANA SP 11 之后,可以使用 Node.js 作為 Hana 的編程接口。SAP 將 Application server 簡稱為 XS。現在 XS 已經演化為 Advanced 版本。為了區別,早期的 XS 被稱為 XS Classical。
從下圖可以看出,和 Hana DB 進行交互的有 HANA XS Classical 、Hana Cloud Platform (HCP) 和 XS Advanced。而能夠運行在 HCP 和 XS Advanced 的編程接口包括 XSJS (SAP 推出的服務器端 JavaScript,但目前看,社區并不活躍)、Node.js、Tomcat / TomEE (Java 應用程序編寫)等。最近測試了 Node.js 編程接口,感覺還不錯。
hdb 模塊
Node.js 的編程接口模塊是 hdb,可以用 npm install hdb 安裝。Github 的源碼地址為:node-hdb。有示例和說明,容易學習。
hdb CRUD
本文打算介紹兩個方面:
-
hdb CRUD 的基本方法;
-
以及如何利用 Node.js 的 express 框架實現 REST 風格 API (Restful API)。
先看看基本使用方法:
var hdb = require('hdb')var client = hdb.createClient({host: '192.168.2.100,port: 30015,user: 'STONE',password: 'pwd' });client.connect(function(err){if (err){return console.error('Connect error', err);}var sql = 'SELECT * FROM STONE.EMP_MASTER';client.exec(sql, function(err, rows){if (err){return console.error('Execute error', err);}console.log('Results:', rows);}); });和前幾篇一樣,仍然使用 STONE.EMP_MASTER 作為數據源。我們注意到,Node.js 廣泛使用異步和回調函數。使用異步的原因是 : Node.js 是單線程的,通過異步來避免阻塞 (blocking)。比如,從Hana 數據庫查詢 employees 表,但不知道需要多久能獲得查詢結果,通過異步機制,數據查詢到之后放在 rows 中。
上面的 SQL 語句沒有參數。下面通過 insert 語句來說明帶參數 SQL 語句的處理方法。
client.connect(function(err){if (err){return console.error('Connect error', err);}var sql = 'INSERT INTO STONE.EMP_MASTER VALUES(?,?,?,?,?,?,?,?)';client.prepare(sql, function(err, statement){if (err){return console.error('Prepare error:', err);}var params = ['9001','Male',18,'test4@qq.com','13800-138000','Bachelor','Married',1];statement.exec(params, function(err, affectedRows){if (err){return console.error('Execute error:', err);}console.log('Affected rows:', affectedRows);});}); });-
client.prepare() 先處理語句,成功后放在 statement 中
-
statement.exec() 語句執行查詢,函數的第一個參數是 SQL 語句的參數。注意這個參數是數組類型,即使只有一個參數,也要使用數組。
提供 REST 風格的 Service
使用 Node.js 的 express 框架來實現。網上有非常多使用 express 創建 REST 風格 API 的教程,這里就不細說步驟了。后面會介紹怎樣在 OpenUI5 中通過 Rest Service 來對對數據庫進行增刪改查。
-
安裝 Node.js
-
創建一個文件夾,在文件夾中運行 npm init 創建 packages.json 文件。
-
安裝 express,這里提供一種方法: npm install express --save。--save 參數會修改 packages.json 文件。
-
安裝 body-parser。這個模塊將處理 post 請求,對 post 請求進行解析。
工程的文件結構如下:
主要文件有:
- server.js : 啟動服務
- dbconfig.js: hana 數據庫連接的配置信息
- emp.controller.js: emp_master 表增刪改查
- emp_routes.js: 路由管理
先說明 package.json 文件,管理 app 依賴的模塊:
{"name": "hana_app","version": "1.0.0","description": "hana in nodejs + express","main": "server.js","dependencies": {"body-parser": "^1.18.2","express": "^4.16.2","hdb": "^0.15.2"},"devDependencies": {},"scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"author": "Stone Wang","license": "MIT" }server.js
var express = require('express'); var bodyParser = require('body-parser');var app = express();// parse requests of content-type - application/x-www-form-urlencoded app.use(bodyParser.urlencoded({extended: true}));// parse requests of content-type - application/json app.use(bodyParser.json());// home page app.get('/', function(req, res){res.json('Welcome.'); });// register routes var route = require('./app/routes/emp.routes.js') route(app);// listen on port 3000 app.listen(3000, function(){console.log('Server is running on port 3000.'); });在 server.js 中定義首頁的響應,注冊路由以及偵聽 3000 端口。
dbconfig.js
保存數據庫的配置信息,是一個對象:
module.exports = {hana:{host: '192.168.2.100',port: 30015,user: 'STONE',password: 'pwd'} };emp.controller.js
var hdb = require("hdb"); var dbconfig = require("../../config/dbconfig.js");var client = hdb.createClient(dbconfig.hana);// list all exports.listAll = function(req, res){var sql = "SELECT * FROM STONE.EMP_MASTER";client.connect(function(err){if (err){res.send({"error": err.message});}client.exec(sql, function(err, rows){if (err){res.send({"error": err.message});}client.end();res.send({rows});});}) };// query by id exports.queryById = function(req, res){var sql = "SELECT * FROM STONE.EMP_MASTER WHERE EMP_ID=?";client.connect(function(err){if (err){res.send({"error": err.message});}client.prepare(sql, function(err, statement){if (err){res.send({"error": err.message});}statement.exec([req.params.emp_id], function(err, rows){if (err){res.send({"error": err.message});}client.end();res.send({rows});});});}); };// create exports.create = function(req, res){var sql = "INSERT INTO STONE.EMP_MASTER VALUES(?,?,?,?,?,?,?,?)";client.connect(function(err){if (err){res.send({"error": err.message});}client.prepare(sql, function(err, statement){if (err){res.send({"error": err.message});}var params = [req.body.EMP_ID,req.body.GENDER,req.body.AGE,req.body.EMAIL,req.body.PHONE_NR,req.body.EDUCATION,req.body.MARITAL_STAT,req.body.NR_OF_CHILDREN];statement.exec(params, function(err, data){if (err){res.send({"error": err.message});}client.end();res.sendStatus(200);});});}); };// update exports.update = function(req, res){var sql = "UPDATE STONE.EMP_MASTER SET GENDER=?, AGE=?, EMAIL=?, PHONE_NR=?, EDUCATION=?, MARITAL_STAT=?, NR_OF_CHILDREN=? WHERE EMP_ID=?";client.connect(function(err){if (err){res.send({"error": err.message});}client.prepare(sql, function(err, statement){if (err){res.send({"error": err.message});}var params = [ req.body.GENDER,req.body.AGE,req.body.EMAIL,req.body.PHONE_NR,req.body.EDUCATION,req.body.MARITAL_STAT,req.body.NR_OF_CHILDREN,req.params.emp_id];statement.exec(params, function(err, data){if (err){res.send({"error": err.message});}client.end();res.sendStatus(200);});});}); };// delete exports.delete = function(req, res){var sql = "DELETE FROM STONE.EMP_MASTER WHERE EMP_ID=?";client.connect(function(err){if (err){res.send({"error": err.message});}client.prepare(sql, function(err, statement){if (err){res.send({"error": err.message});}statement.exec([req.params.emp_id], function(err, data){if (err){res.send({"error": err.message});}client.end();res.sendStatus(200);});});}); };emp.routes.js
module.exports = function(app){var empController = require("../controllers/emp.controller.js");// list allapp.get('/employees', empController.listAll);// query by IDapp.get('/employee/:emp_id', empController.queryById);// createapp.post('/employee/create', empController.create);// updateapp.put('/employee/:emp_id',empController.update);// deleteapp.delete('/employee/:emp_id', empController.delete); };使用 Postman 測試
在項目文件下,通過 node server.js 啟動服務。然后打開 Postman 進行測試。以下是部分截圖。
- listAll
- create
- update
- delete
- update
?
轉載于:https://my.oschina.net/fcweb/blog/1813688
總結
以上是生活随笔為你收集整理的利用 Node.js 实现 SAP Hana 数据库编程接口的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mybatis之设计模式之装饰者模式
- 下一篇: MySQL安装时出现的问题