博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用 Node.js 实现 SAP Hana 数据库编程接口
阅读量:5950 次
发布时间:2019-06-19

本文共 7822 字,大约阅读时间需要 26 分钟。

  hot3.png

自 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 的源码地址为:。有示例和说明,容易学习。

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-urlencodedapp.use(bodyParser.urlencoded({extended: true}));// parse requests of content-type - application/jsonapp.use(bodyParser.json());// home pageapp.get('/', function(req, res){    res.json('Welcome.');});// register routesvar route = require('./app/routes/emp.routes.js')route(app);// listen on port 3000app.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 allexports.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 idexports.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});            });        });    });};// createexports.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);            });        });    });};// updateexports.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);            });        });    });};// deleteexports.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

 

转载于:https://my.oschina.net/fcweb/blog/1813688

你可能感兴趣的文章
【Testin实验室】MoiMark安卓中国终端体验性能排行榜(11月报)
查看>>
Wireshark入门与进阶---数据包捕获与保存的最基本流程
查看>>
讲义笔记
查看>>
Spring中HibernateCallback的用法(转)
查看>>
编译原理——语言处理程序
查看>>
IOS中通知中心(NSNotificationCenter)的使用总结
查看>>
TOP 10开源的推荐系统简介
查看>>
apache开源项目--nutch
查看>>
Oracle12C 怎样导入scott用户
查看>>
jQuery Validate 表单验证插件----在class属性中添加校验规则进行简单的校验
查看>>
Google C++ style guide——命名约定
查看>>
html image -- data:image/png;base64
查看>>
Mybatis bug修正
查看>>
ubuntu(14.04) 下安装yaf拓展
查看>>
C++产生随机数
查看>>
IOS-程序员和设计师必备的20个CSS工具
查看>>
HPU周赛题目解析
查看>>
iOS_GET_网络请求
查看>>
[转]WampServer localhost 图标不显示解决办法
查看>>
uva 10816 Travel in Desert(简单的好题~两种方法)
查看>>