完成上一篇的配置,现在我们可以在 SAP 系统中创建基于 SAP Netweaver Gateway 的 OData Service。本篇主要是介绍在 SAP 系统中创建 OData service 的过程,为后续在 OpenUI5 中通过 OData Model 使用 SAP 系统提供的 OData 数据服务。SAP OData service 本身包含很多知识点,也需要系统学习。
本次要实现的功能:创建数据库表 zemployee,并基于 SAP Netweaver OData Service, 实现对 zemployee 的增删改查。
1. 创建 zemployee 数据库表
使用事务码 SE11 创建 zemployee 表。因为本文主要介绍 OData service 创建的过程,所以并不打算详细说明创建表的细节。为了足够简单, zemployee 表只包含 empid
, empname
, empaddr (employee address)
三个字段。
2. 创建基于 Netweaver Gateway 的 OData Service
2.1 创建 Gateway service project
通过事务码 SEGW,进入下面的界面:
点击 Create Project 按钮,创建一个 Gateway service project, 将 project 命名为 zempprj
。点击 「Local Object」按钮,zempprj 项目创建成功:
我们可以到,Gateway service 分为四个部分 (左边的 panel):
-
Data Model: 数据模型,主要包括
Entity type
,( 比如说 product entity,customer entity 等),Entity set
(Entity 的集合,多笔数据) 和Association
(Entity 之间的关联)Service Implementation: Entity set 的 CRUD 实现
Runtime Artifacts: 基于 Entity set 的代码框架,包括数据模型 (Data model),数据提供者 (Data provider)
Service maintenance:注册服务,测试服务。
2.2 创建 Data Model
1) 创建 Entity
选中 Data Model,右键,Import -> DDIC Structure,表示从 DDIC 中导入结构作为 Entity:
将 Entity type 命名为 Employee, 字段来自 DDIC 的 zemployee 表:
选中 zemployee 表的所有字段,点击 Next 按钮:
系统进入如下界面。在这个界面中,定义 Employee 这个 entity 的字段属性。将 mandt 和 empid 定义为 primary key,并将 Name 的名称规范为首字母大写。
属性定义完成后,左边的 panel 中, Properties 下面可以看到主键和属性:
2) 创建 Entity set
选中左边 Panel 的 Entity Set,右键,Create。将 Entity set 命名为 EmployeeCollection
, Entity type 为刚刚创建的 Employee
。
定义 EmployeeCollection
可以进行 CRUD:
2.3 Generate Runtime Objects
选中左边 Panel 的 Runtime Artifacts,点击 Generate Runtime Objects 按钮,系统进入下面的界面:
保持所有默认不变,点击 Continue 按钮。系统生成 Runtime Objects。
2.4 服务注册
前面我们在 SAP 系统中创建了 Gateway service 的别名,我们可以看到,这个别名出现在 Service maintenance 下面。双击可以进入下面的界面。
此时, Registration status 是没有状态的,点击 Register 按钮,系统弹出对话框:
选择 Sytem Alias 为 local,进入下面的界面
确认,完成系统注册。
2.5 测试 OData service
尽管我们还没有编写 OData service 的实现代码,但已经可以通过 Browser 或者 SAP Gateway Client 进行测试了。双击左边 Panel Service maintenance 下的 localgateway,点击右边出现的 Maintain 按钮,进入下面的界面:
我们可以通过点击左下角的 Call Browser 或者 SAP Gateway Client 按钮进行测试。当点击 SAP Gateway Client 按钮的时候,界面如下:
后面我们会多次进入到这个界面,进行 CRUD 的测试。
利用 Browser 来进行测试,则有可能碰到一些问题。在这里介绍两种极有可能的情况及解决方法:
一是点击 Call Browser 按钮,系统显示 host name 或 port 没有配置好,这个时候,使用事务码 SMICM,然后通过菜单 Goto -> Services,看看主机和端口是否配置好,是否启用。
另外,还要注意域名解析,如果服务器没有在 Internet 上公开,这个 host name 不能通过 Internet 网进行访问,则需要设置本机的 hosts 文件,让本机指向这个域名。Windows 10 中 hosts 文件的位置在 C:\Windows\System32\drivers\etc
文件夹中。
2.6 服务实现 (Service maintenance)
服务实现是指提供 CRUD 的具体实现,因为读取数据的时候,存在 Entity 和 EntitySet,SAP 一般把读取 Entity 叫做 Read,把读取 EntitySet 叫做 Query。在 SEGW 界面中 展开 Service Implementation:
我们需要编写具体的代码,这样外部才能实现对 SAP 数据的增删改查。首先我们来看看 GetEntitySet
方法的编写过程。
Query
选中 GetEntitySet (Query)
,右键,Go to ABAP Workbench。系统提示:
点击「确认」按钮,进入下面的界面:
找到 EMPLOYEECOLLECTI_GET_ENTITYSET
,右键,选择 Redefine,改写这个方法。其它的方法创建过程类似,不再重复说明。
改写后 employeecollecti_get_entityset
方法代码如下:
METHOD employeecollecti_get_entityset.
SELECT * FROM zemployee
INTO CORRESPONDING FIELDS OF TABLE et_entityset.
ENDMETHOD.
et_entityset
是代码框架预设的方法参数,通过追踪,我们知道,它是基于 zemployee
的内表类型。
测试:
在 SAP Gateway Client 界面中:
- HTTP Method: GET
- Request URL:
/sap/opu/odata/sap/ZEMPPRJ_SRV/EmployeeCollection?$format=json
系统返回的结果:
我们总可以从 SEGW 进入服务维护和 Gateway client 界面。也可以通过另外的事务码:
- Service maintain:
/IWFND/MAINT_SERVICE
。这两个事务码比较怪,不通过/o
系统提示错误。所以应该输入/O/IWFND/MAINT_SERVICE
。 - SAP Gateway client:
/o/iwfnd/gw_client
。
Read
实现 GetEntity (Read)
方法:
METHOD employeecollecti_get_entity.
DATA: ls_key_tab TYPE /iwbep/s_mgw_name_value_pair,
l_empid TYPE zemployee-empid,
ls_employee TYPE zemployee.
READ TABLE it_key_tab WITH KEY name = 'EmpId' INTO ls_key_tab.
l_empid = ls_key_tab-value.
SELECT SINGLE * FROM zemployee INTO er_entity WHERE empid = l_empid.
ENDMETHOD.
SAP Gateway Client 测试:
- HTTP Method: GET
Request URL:
/sap/opu/odata/sap/ZEMPPRJ_SRV/EmployeeCollection(Mandt='100',EmpId='1')?$format=json
Response:
{
"d" : {
"__metadata" : {
"id" : "http://dph01.ourdomain:8180/sap/opu/odata/sap/ZEMPPRJ_SRV/EmployeeCollection(Mandt='100',EmpId='1')",
"uri" : "http://dph01.ourdomain:8180/sap/opu/odata/sap/ZEMPPRJ_SRV/EmployeeCollection(Mandt='100',EmpId='1')",
"type" : "ZEMPPRJ_SRV.Employee"
},
"Mandt" : "100",
"EmpId" : "1",
"EmpName" : "Stone",
"EmpAddr" : "Wuhan"
}
}
Create
实现 Create
方法
METHOD employeecollecti_create_entity.
DATA: ls_employee TYPE zemployee.
" Get requested data from input
io_data_provider->read_entry_data( IMPORTING es_data = er_entity ).
MOVE-CORRESPONDING er_entity TO ls_employee.
INSERT zemployee FROM ls_employee.
ENDMETHOD.
SAP Gateway Client 测试:
因为 Create 操作需要数据,我们可以先用 GET 方法得到一笔数据,更改后再用 POST 方法进行提交。操作步骤如下:
点击 「Use as request」,将获取的数据进行更改后提交:
返回的状态码为 201 则表示成功。
Update
实现 Update
方法:
method EMPLOYEECOLLECTI_UPDATE_ENTITY.
DATA: ls_employee TYPE zemployee.
" Get requested data
io_data_provider->read_entry_data( IMPORTING es_data = er_entity ).
MOVE-CORRESPONDING er_entity TO ls_employee.
MODIFY zemployee FROM ls_employee.
endmethod.
Update 的测试使用 PUT 方法:
- HTTP Method: PUT
- Request URI:
/sap/opu/odata/sap/ZEMPPRJ_SRV/EmployeeCollection(Mandt='100',EmpId='3')
Delete
实现 Delete 方法:
METHOD employeecollecti_delete_entity.
DATA: ls_key_tab TYPE /iwbep/s_mgw_name_value_pair,
l_empid TYPE zemployee-empid,
ls_employee TYPE zemployee.
READ TABLE it_key_tab WITH KEY name = 'EmpId' INTO ls_key_tab.
l_empid = ls_key_tab-value.
DELETE FROM zemployee WHERE empid = l_empid.
ENDMETHOD.
测试比较简单,不再赘述。