SAP Hana 資料庫程式設計介面
自 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,'[email protected]','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 all
app.get('/employees', empController.listAll);
// query by ID
app.get('/employee/:emp_id', empController.queryById);
// create
app.post('/employee/create', empController.create);
// update
app.put('/employee/:emp_id',empController.update);
// delete
app.delete('/employee/:emp_id', empController.delete);
};
使用 Postman 測試
在專案檔案下,通過 node server.js
啟動服務。然後開啟 Postman 進行測試。以下是部分截圖。
- listAll
- create
- update
- delete
- update
相關推薦
SAP Hana 資料庫程式設計介面
自 SAP HANA SP 11 之後,可以使用 Node.js 作為 Hana 的程式設計介面。SAP 將 Application server 簡稱為 XS。現在 XS 已經演化為 Advanced 版本。為了區別,之前的 XS 被稱為 XS Classic
SAP HANA資料庫架構部署方法
HANA作為記憶體資料庫,在實現高效能訪問的同時,必須也要有穩定的架構,今天我們就來看看企業部署SAP HANA時應該如何來設計資料庫的架構。
SAP HANA資料庫中如何使用正則表示式
作為一個程式設計師小白,剛進公司上班兩個周,我開始熟悉並參與公司的一個專案(當然,只是做一些最簡單的查詢來練練手啦,複雜的也不會。。。),帶我的同事讓我在某個表的資料列表頁面設定幾個按鈕,來根據過期狀態查詢記錄,於是我開始了,這個專案的資料庫是用hana來管理
SAP HANA資料庫安裝
SAP HANA是一個全新設計的記憶體資料庫系統,他即支援傳統的行式儲存也支援列式儲存。HANA資料庫具有很高的效能、併發能力和可擴充套件性。HANA即可以支援OLTP應用也可以支援OLAP系統。 我們都知道,制約資料庫系統性能提升的關鍵瓶頸是I/O。為了解決這個問題
PHP訪問SAP HANA資料庫
最近接到一個專案,因為客戶嫌LUMIA的 License太貴,使用者又多,所以想用省錢的辦法看SAP HANA的報表(B/S架構),所以給了用PHP做HANA報表的方案。 首先要考慮的是連線問題,原來我做專案時,都是優先考慮PHP ADODB元件,但PHP ADODB元件中
Python專案之連線SAP HANA資料庫
因為公司目前用的是SAP HANA平臺在做資料分析建模工作,我想引用python做一些演算法分析工作,這就引入了Python連線HANA 方法。python 與 hana 連線採用pyhdb庫,使用方便。pyhdb 庫:https://pypi.org/project/pyh
幾種資料庫程式設計介面
從功能簡單的資料庫(如Jet Engine)到複雜的大型資料庫系統(如oracle),VC++6.0都提供了一些程式設計介面。本文主要介紹以下五種: 1.ODBC API; 2.MFC ODBC類; 3.MFC DAO類;(資料訪問物件) 4
利用Veeam保護SAP HANA資料庫
利用Veeam保護SAP HANA資料庫 前言 針對越來越多的SAP HANA備份需求,我們Team翻譯、整理、借鑑了Veeam 的SAP HANA 大神 Clemens Zerbe 和 Ali Salman 的文章,本著力求實用的原則。希望能給我們中國的Partner一些實際的幫助,本文會在以後以多個章節的
嵌入式linux-sqlite3資料庫,資料庫基本知識,sqlite3系統命令,sqlite3 SQL命令,SQLite程式設計介面
文章目錄 1,資料庫基本概念:資料(Data)、資料庫 (Database) 2,常用的資料庫 3,基於嵌入式的資料庫 4,SQLite基礎 5,sqlite3資料庫的安裝 6,建立資料庫 7,SQLite基本命令 7
SAP HANA Studio 連線不上資料庫或者是報使用者名稱密碼失效
SAP HANA Studio 連線不上資料庫:使用了一段時間的SAP HANA Studio 經常會出現:''The DCA hanasvr-10 00(<user id>) could not create connection''Error when co
NBU 恢復 SAP HANA
nbu7 netbackup7 備份恢復sap hana通過SAP Studio恢復通過SAP STUDIO,右鍵實例,選擇RECOVERY。恢復會自動停止數據庫。2. 選擇第一項恢復到最新狀態3. 直接使用默認4. 默認等待一會會自動查詢到備份集本文出自 “Contoso” 博客,請務必保留此出處http:
NBU 備份 SAP HANA
nbu7 netbackup7 備份恢復sap hana一. 鏈接libelf.so.0檢查並確定 libelf.so.0 通過符號鏈接到 libelf.so.0.8.13 文件。這些文件位於 /usr/lib64/sapprd01:/#cd /usr/lib64/sapprd01:/usr/lib64 #l
Oracle GoldenGate 支持 從SAP HANA database抽取或者復制數據到SAP HANA database 嗎?
skill platform offer rep iat data- big data ble inf Oracle GoldenGate 支持 從SAP HANA database抽取或者復制數據到SAP HANA database 嗎? 來源於: Does
SAP HANA中的SLT簡介
同步 image separate extra tle 有著 uri 細節 http 在以SAP系統作為主要ERP的企業中,不同系統之間的數據庫數據同步是個重要的工作。對於這種需求,除了開發ABAP接口之外,也有高效的工具可用。SLT就是其中之一。 SLT是SAP的第一個
聯想項目結束了,聊聊華為SAP HANA項目八卦
one sap hana poc 休閑 閑聊 跳槽 環境 問題 clear 聯想項目結束了,聊聊華為SAP HANA項目八卦【轉】 Tagged with SAP HANA, 華為 原文:http://www.hanapost.com/huawei/ 聯想項目結束了,聊聊
BlockChain技術系列(七)- 應用程式設計介面
一個遵循MVC-B架構的應用– Model, View, Control, BlockChain. VIEW LOGIC – 與控制邏輯整合的移動或WEB 使用者介面。 CONTROL LOGIC – 協調使用者介面、
BlockChain技術系列(六)- 應用程式設計介面
fabric的主要介面是REST API。 REST API允許應用註冊使用者,查詢區塊鏈,併發布交易。 CLI為了開發,同樣提供有效API的子集。CLI允許開發人員能夠快速測試鏈碼或查詢交易狀態。 應用程式通過REST API與非驗證的 peer 節點,這將需要某種形式的認證,以確保實
typeScript(8):ts面向物件程式設計/介面
在通常情況下,介面是用來定義一些規範,使用這些介面,就必須實現按照介面中的規範來走。 在面向物件的語言中,術語interface經常被用來定義一個不包含資料和邏輯程式碼但是用來簽名定義了行為的抽象型別。 認識介面 定義介面的關鍵字是interface。我們現在就
瞭解SAP HANA租戶庫Ⅱ
更多內容關注公眾號:SAPtechnical 點選進入:瞭解SAP HANA租戶庫Ⅱ 從第一篇《瞭解SAP HANA租戶庫Ⅰ》的介紹中我們瞭解到,SAP HANA 2.0 SPS01已經把多租戶作為預設選項了,單容器租戶將不是預設配置,因此,如果將單個容器系統從任何較低
SAP HANA租戶庫Ⅰ
更多內容關注公眾號:SAPtechnical SAP HANA 1.0從SPS10開始就推出了多租戶庫,而在SAP HANA 2.0 SPS01開始,多租戶資料庫容器,我們簡稱MDC將成為SAP HANA系統的唯一操作模式。也就是說,我們將無法再去操作單容器模式的系統了。