还在写SQL做SAP二开?通过RFC调用NetWeaver,让HANA数据库操作更可靠
相比于从零开始构建全套信息化系统,基于成熟的ERP等行业软件做二次开发是更多中大型企业应对个性化软件需求的首选方案。如何在二开模块中,可靠地对成品软件的数据库进行读写操作,以满足单据自动创建、元数据自动同步等系统集成要求,是摆在开发者面前的难题。今天,我们基于活字格低代码平台的技术支持工作中较为常见SAP HANA为例,为您介绍几种典型的路线。
方案1:通过ODBC直连HANA,操作原始数据
SAP HANA的客户端程序中提供了ODBC的数据源,这就使得开发团队可以直接通过ODBC连接HANA数据库,并通过SQL语句对数据库中的原始数据进行读写操作。
(通过ODBC操作HANA)
首先,我们需要在开发环境、测试环境和生产环境的服务器上,配置SAP提供的ODBC数据源。在安装有SAP Client(推荐x64)之后,打开系统的odbc数据源管理程序(注意区分64为和32位,需要和SAP Client保持一致)。在"系统DSN"选项卡中点击"添加",选择HDBODBC,之后按照界面提示输入数据源的名称,如"HANA-测试库"、服务器IP地址、用户名和密码就可以了。
(创建到HANA的ODBC数据源)
配置完成后,我们就可以像操作其他数据库一样,对 SAP HANA的数据进行读写了。回到活字格里面,我们使用"连接到外联表"功能,引入HANA中需要操作的所有数据表。之后就可以用拖拽的方式完成数据绑定,或者在服务端拼接和执行SQL语句了。
(在活字格低代码平台中引入ODBC数据源)
如果仅仅是读取元数据或者一些简单的单据,这种方案确实是一个简单的办法。但是,SAP的数据表结构复杂,且缺乏有效的数据库脚本跟踪能力,我们很难确定一个单据创建过程需要操作哪几张表的哪些字段。所以,在涉及到稍微复杂一点的应用场景时,通过ODBC直接操作原始数据的做法的风险较高。
(纯代码,通过ODBC操作HANA的数据表)
基于多年的技术支持经验,我们通常不会推荐客户采用这个方案。
方案2:调用NetWeaver API,操作业务对象
SAP显然也清楚开发者直连HANA,操作原始数据带来的可靠性风险。所以,SAP推出了NetWeaver集成平台,给开发者提供了一个原厂级二开解决方案,"尽量"确保写入的数据不会对SAP系统运行造成威胁。然而,这个平台的开发成本依然不如人意,以至于大多数开发者在二开项目之初就放弃了这个方案。不过,NetWeaver中对数据表中原始数据的操作封装成对业务对象的操作,并加入了一些必要的校验逻辑,这一点对于二开来说还是非常有意义的。更重要的是,这些封装的接口是开放的,即便我们采用了其他的二开方案,依然可以通过RFC协议,调用NetWeaver提供的HANA操作能力,从而避免直接读写原始数据带来的风险。
引入NetWeaver后,二开模块可以不再直接操作HANA数据库,而是通过位于二开服务器上的RFC桥(如果对可维护性要求不高,也可直接集成到二开模块中)和位于SAP集群中的NetWeaver来完成。二开模块通过HTTP等协议调用RFC桥,RFC桥则通过RFC协议转调NetWeaver,NetWeaver则负责在HANA上直接对应的SQL语句。
之所以我们将RFC调用部分抽象成一个专门的RFC桥模块,主要是考虑到这部分采用了一个第三方组件库(SAP原厂的.NET SDK口碑不佳),将其与二开模块进行隔离,可有效降低维护风险。因为客户采用的是低代码的开发方式,这个RFC桥的实现方式为基于活字格服务端编程接口开发的自定义WebAPI。对于纯代码开发者来说,RFC桥通常是一个ASP.NET MVC或Java SpringBoot的Web服务。在实现逻辑和架构原理上,低代码与纯代码大同小异,都需要通过写代码的方式完成。
(通过RFC + NetWeaver操作HANA)
步骤一:使用C#开发调用NetWeaver的RFC桥
在这一步中,我们需要使用到Visual Studio(截屏是VS2021)、活字格服务端编程接口(截屏是活字格V7.0 Update1)、SAP NetWeaver RFC SDK(截屏是7.5)和开源项目SapNwRfc(https://github.com/huysentruitw/SapNwRfc)。其中SAP的SDK需要客户使用SAP账号,从SAP官网下载。
首先,我们在VS2021中创建.NET 4.7.2的类库工程,引用RFC SDK中lib文件夹的sapnwrfc.dll;然后通过nuget查找并安装SapNwRfc包和Microsoft.AspNetCore.Http.Abstractions包(活字格服务端编程接口需要依赖这个包);最后引用活字格服务器程序安装目录中的GrapeCity.Forguncy.ServerApi.dll。为了确保RFC SDK的正常运行,简化部署操作,我们更建议将RFC SDK的文件直接拷贝到系统盘下的某个目录,并且在系统的PATH变量中追加这个目录下面的lib文件夹,以确保运行时可以准确找到所引用的sapnwrfc.dll。
(Nuget中的SapNwRfc包)
然后,我们需要根据SAP的文档说明,创建RFC的传入和传出参数所对应的类。SAP为每一个NetWeaver接口准备一个Excel文件,记录了方法名,传入参数和传出参数的类型和结构。我们只需要找到所需调用的那个接口对应的Excel文件,根据文档要求创建入参和出参对应的class即可。需要注意的是,属性的名称、SapName标签的值需要和文档中的参数名严格保持一致。以创建供应商为例,我们需要创建传入参数类:CreateVendorParameters和传出参数类:createVendorParametersObj。
(NetWeaver中创建供应商的接口所对应的参数结构)
然后,我们在工程中创建WebAPI,一个继承自ForguncyApi的类GetSAPInfo,然后创建POST请求的响应方法CallRFCFunction(方法名和类名组成了URL的Path部分)。在代码中,我们从请求中读取连接字符串、需要使用的方法和参数,调用SapConnection类的对应方法进行处理,最后把结果序列化后返回给该WebAPI的调用者。和属性名称一样,调用SapConnection时传入的方法名也需要和文档中的文字严格保持一致,如创建供应商的方法名为ZLIFNR_CREATE。
(RFC桥的WebAPI实现)
根据既往经验,为了降低调用RFC桥的开发者的学习门槛,让他们也可以参照SAP提供的文档直接进行操作,我们推荐将所有用到的接口统合到一个WebAPI中,在代码中通过SAP的方法名进行switch分支。
如需使用这些示例代码,可以从码云获取:https://gitee.com/GrapeCity/lowcode_extention_demo_hana_via_sap_rfc
步骤二:在活字格中调用RFC桥
使用活字格服务端编程接口开发出的WebAPI与纯代码开发出的WebAPI的使用方法完全一致。在使用活字格开发业务系统的时候,都可以通过"发送HTTP请求"命令来调用。
首先,开发和测试的环境下,我们通常会连接不同的SAP数据库,所以,我们需要将连接NetWeaver所需的必要信息存储到数据库中,随程序一同发布,而不是写死在代码或全局配置文件中。
(存储在数据库中的NetWeaver连接信息)
在需要操作SAP的数据时,我们需要先使用"设置变量命令",从数据库中读取当前环境所使用的HANA数据库的参数,拼接成连接字符串;然后使用"发送HTTP请求命令",通过调用RFC桥的WebAPI。
按照步骤一中RFC桥的实现,其URL地址是customapi/{类名}/{方法名}。我们还需要在HEAD中设置连接字符串和方法名(来自SAP提供的Excel文档,如ZLIFNR_CREATE)。
(配置NetWeaver的连接字符串和方法名)
而具体的请求参数则需要在BODY中进行设置,将二开系统的业务数据作为参数传递给HANA,执行对应的数据操作,最终达到系统集成的效果,如这里举例的创建供应商档案。
(配置传递给NetWeaver的业务数据)
下面是我们帮助客户进行技术评估时,快速构建的活字格与SAP NetWeaver集成的Demo。如需使用这个工程,可以从码云获取:https://gitee.com/GrapeCity/lowcode_demo_hana_via_sap_rfc
(使用活字格集成SAP HANA的效果)
讨论
为了帮助开发者做二次开发,SAP和用友等主流厂商大多提供了直连数据库和封装业务接口两种开发模式。在纯代码开发方式下,两种模式最大的差异在于前者性能上限更高,后者可靠性更强。
进入低代码时代后,封装业务接口的模式体现出了更强的竞争优势。比如今天的例子中,在RFC桥的帮助下,业务应用的开发者能通过可视化配置,轻松实现对HANA数据库的读取和写入操作,而这一切,无需掌握任何一门编程语言。专业程序员借助平台的编程接口扩展平台能力,非专业程序员通过使用这些能力,可视化完成系统开发,这种"混合模式"正在成为低代码开发的主流。
还在写SQL做SAP二开?通过RFC调用NetWeaver,让HANA数据库操作更可靠的更多相关文章
- 屌炸天实战 MySQL 系列教程(二) 史上最屌、你不知道的数据库操作
此篇写MySQL中最基础,也是最重要的操作! 第一篇:屌炸天实战 MySQL 系列教程(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:屌炸天实战 MySQL 系列教程(二) 史上最屌.你不 ...
- 《你还在写sql语句吗?》人生苦短,进入MybatisPlus的丝滑体验
一.发展历程 依稀记得大学期间,类中写sql语句的日子,一个sql语句占据了大部分时间,到后来hibernate的出现算是解决了这一痛点.工作 后,我们又接触到了mybatis这样的框架,瞬间感觉这个 ...
- [SQL Server]用 C# 在 LinqPad 建立 Linked Server 跨服务器数据库操作
在涉及老项目数据迁移的时候,数据库结构已经完全发生变化,而且需要对老数据进行特殊字段的处理,而且数据量较大,使用Navicat导出单表之后,一个表数据大概在100多万的样子,直接导出SQL执行根本行不 ...
- NC57,NC63-NC二开经验总结
版主2010级市场营销专业本科生 2013年8月入达内培训Java相关技术 12月入职,做用友NC的二次开发工作 2015年4月离职,4中下旬入职一家互联网金融企业 下面是做NC二开期间积累的一些常用 ...
- SQL开发技巧(二) 【转】感觉他写的很好
本文转自: http://www.cnblogs.com/marvin/p/DevelopSQLSkill_2.html 本系列文章旨在收集在开发过程中遇到的一些常用的SQL语句,然后整理归档,本系列 ...
- Python 数据分析:让你像写 Sql 语句一样,使用 Pandas 做数据分析
Python 数据分析:让你像写 Sql 语句一样,使用 Pandas 做数据分析 一.加载数据 import pandas as pd import numpy as np url = ('http ...
- 还在用ABAP进行SAP产品的二次开发?来了解下这种全新的二次开发理念吧
Jerry从2018年底至今,已经写了一系列关于SAP Kyma的文章,您可以移步到本文末尾获得这些文章的列表.Kyma是SAP开源的一个基于Kubernetes的云原生应用开发平台,能够允许SAP的 ...
- Spring Boot 入门系列(二十七)使用Spring Data JPA 自定义查询如此简单,完全不需要写SQL!
前面讲了Spring Boot 整合Spring Boot JPA,实现JPA 的增.删.改.查的功能.JPA使用非常简单,只需继承JpaRepository ,无需任何数据访问层和sql语句即可实现 ...
- 在mybatis中写sql语句的一些体会
本文会使用一个案例,就mybatis的一些基础语法进行讲解.案例中使用到的数据库表和对象如下: article表:这个表存放的是文章的基础信息 -- ------------------------- ...
随机推荐
- CDN 的缓存与回源机制解析
CDN的缓存与回源机制解析 CDN (Content Delivery Network,即内容分发网络)指的是一组分布在各个地区的服务器.这些服务器存储着数据的副本,因此服务器可以根据哪些服务器与用户 ...
- 增删改查简单的sql语句
insert INSERT INTO t_stu (name,age) VALUES ('wang',12) INSERT INTO t_stu VALUES(NULL,' ...
- python——平时遇到问题记录
# pyhs2安装 #centos yum install groupinstall 'development tools' yum install python34-devel yum instal ...
- Python篇函数总结【输出函数】
1.raw_input("\n\nPress the enter key to exit.") 以上代码中 ,"\n\n"在结果输出前会输出两个新的空行.一旦用 ...
- 如何在Kubernetes 里添加自定义的 API 对象(一)
环境: golang 1.15 依赖包采用go module 实例:现在往 Kubernetes 添加一个名叫 Network 的 API 资源类型.它的作用是,一旦用户创建一个 Network 对象 ...
- 1day漏洞反推技巧实战(3)
代码审计必备技能,github代码对比,写一笔: 搜索某开源组建漏洞,搜索出来某个版本rce: 通过消息得出:存在漏洞版本:1.10.10 ,修复漏洞版本1.10.11 去github寻找apache ...
- 针对某p社游戏某整合包的研究
软件分析 垃圾re手 最近在玩群星 创意工坊里面下载了整合包 进群下载排序文件后竟然发现要付费() 28R够吃一顿好的 马上来分析一下这个软件 这是一个四版整合包的mod安装器 其中樱花远征和新星纪元 ...
- Rust语言开发
Rust开发 第一个程序 fn main() { println!("Hello, world!"); // 带!号的都是宏 并不是函数 } fn main() { let nam ...
- [LeetCode]35.搜索插入位置(Java)
原题地址: search-insert-position 题目描述: 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引.如果目标值不存在于数组中,返回它将会被按顺序插入的位置. 请必须使 ...
- Node.JS学习——学习笔记
Node.JS--学习笔记 2020年02月23日11:52:01 我打算自学NodeJS-通过阅读NodeJS官网来完成. https://nodejs.org/dist/latest-v13.x/ ...