头图

Deep Create 也称 Deep Insert,是 OData 协议 V2 和 V4 里的术语,允许客户端在单次请求中,创建具有复杂关联关系的实体。

这种操作在涉及到多个相关对象需要在数据库中以事务性的方式被创建时,显得尤为重要。

所谓复杂关联关系,在面向对象软件建模领域,通常分为三种耦合级别从松到紧的类别:Association, Aggregation 和 Composition.

Association(关联)

Association 是最基础的关系类型,它描述的是两个独立类之间的一种松散的关联关系。

通常,一个类的实例会知道另一个类的实例,并且它们之间可以互相调用对方的方法或访问彼此的属性。Association 并不意味着两个对象的生命周期相关联,它们可以独立存在。

现实世界中的例子: 假设有 Teacher 和 Student 类。在学校的应用场景中,教师和学生之间存在一种关联关系,因为教师可能会教多个学生,而学生也可能会被多个教师教导。这种关系是双向的,但并不意味着教师的存在依赖于某个学生,反之亦然。两个对象可以独立存在。

Aggregation(聚合)

Aggregation 是一种特殊类型的关联关系,它表示的是整体和部分(whole-part)的关系。

在这种关系中,部分对象可以独立于整体对象存在。

换句话说,聚合中的部分对象可以在多个整体对象中共享,且它们的生命周期独立于整体对象。

现实世界中的例子:考虑部门(Department)和员工(Employee)的关系。

一个部门可以有多个员工,而每个员工也可以属于多个部门。员工可以在部门之外独立存在,如果某个部门被撤销消失,员工并不会随之消失,因为他们可以属于其他的部门,或独立存在。

Composition(组合)

Composition 是一种更强的聚合关系,表示整体与部分之间更紧密的联系。在这种关系中,部分对象的生命周期完全依赖于整体对象。

一旦整体对象被销毁,部分对象也会随之被销毁。组合通常用来描述一种拥有关系(has-a),其中整体对象拥有部分对象。

SAP 从业者最熟悉不过的订单抬头与行项目,行项目与 Schedule Line 之间,就是一种 Composition 关系。

在传统的 RESTful API 中,如果需要创建一个包含多个彼此关联实体的结构,通常需要多次请求。首先需要创建主实体,然后分别为每个从属实体发送单独的创建请求。这不仅增加了网络通信的开销,也使得整个操作更容易出现数据不一致的问题,尤其是在网络异常或部分请求失败的情况下。

OData V2 / V4 协议引入了 Deep Create/Insert 概念,允许客户端在一次请求中发送包含所有相关实体的复杂数据结构。OData 实现端解析客户端发送过来的结构之后,在同一个事务中完成所有实体的创建工作,解决了上述传统 Restful API 调用的多次请求问题。

使用事务码 SEGW 开发的 SAP OData 服务,支持 OData 协议的 Deep Create 概念,能给应用程序带来如下好处:

  1. 减少网络开销:Deep Create 能够减少通过网络发送的请求数量。与逐个实体发送请求相比,Deep Create 在一个请求中包含所有相关的实体,从而减少网络延迟并提升整体性能。
  2. 保持原子性和数据一致性:Deep Create 支持原子操作,确保请求中的所有实体要么全部成功创建,要么一个都不创建。原子操作有助于在 SAP 系统中保持数据的一致性和完整性。
  3. 简化客户端代码:Deep Create 使得客户端代码更加简洁高效,后者只需发送一个包含主要实体及其相关实体的结构化请求,减少了管理多个请求和处理实体间依赖关系的复杂性。
  4. 事务支持:SAP OData 服务通常与具有事务处理能力的 SAP 系统集成。Deep Create 利用这一点,确保单个请求中的所有更改都作为一个事务来处理。这意味着如果请求中的任何部分失败,所有更改都会被回滚,确保数据的一致性。

SAP 帮助文档给出了 Deep Create 场景下,Request Body 维护待创建数据的一些例子。

这些例子里,通过 EntityType A 和 B 的不同名称的属性,包含相同值的做法,来描述 A 和 B 的关联关系。比如帮助文档中的 Team_ID 和 Team_Identifier, MANAGER_ID 和 ID 这两对字段。

我们来看个 SAP Fiori 使用 Deep Create 的实际例子。

SAP CRM My Opportunities Fiori 应用,点击创建图标之后,维护完待创建的订单行项目数据之后:

垂直向下滑动,来到 Sales Cycle,Sales Area 和 Product 这几个关联实体的数据维护界面:

从 OData 模型设计上说,Sales Cycle,Sales Area 和 Product,都是 Opportunity OData 模型里的三个子节点,从 Opportunity 父节点出发,通过下图所示的三个 Associations 进行关联。

通过笔者之前的文章保姆级教程:ABAP 通过 HTTP POST 调用 OData 服务创建业务数据的具体例子介绍的方法,可以在 Chrome 开发者工具 Network 里,找到点击 Save 按钮之后,从浏览器向服务器端发起的 Deep Create 请求的 Body Payload:

{"Description":"2022-2-22T22:22:22","ProcessType":"OPPT","StartDate":"2022-2-22T22:22:22","ClosingDate":"2022-8-28T00:00:00","ExpectedSalesVolume":"0","SalesStageCode":"1","UserStatusCode":"E0001","UserStatusText":"Open","PriorityCode":"","PriorityText":"","ProspectName":"4223199","ProspectNumber":"4223199","MainContactName":"","ChanceOfSuccess":"0","ForecastRelevance":true,"CurrencyCode":"","Guid":"00000000-0000-0000-0000-000000000000","Statuses":[{"HeaderGuid":"00000000-0000-0000-0000-000000000000","StatusProfile":"CRMOPPOR","UserStatusCode":"E0001","UserStatusText":"Open","StatusOrderNumber":"01"}],"Products":[{"HeaderGuid":"00000000-0000-0000-0000-000000000000","ProcessingMode":"A","ProductGuid":"00163EA7-1FFC-1EE1-A7E6-1543AD7395C1","ProductId":"AWEHFOIQF","ProductName":"blabla","Quantity":"1","Unit":""}],"SalesTeam":[{"HeaderGuid":"00000000-0000-0000-0000-000000000000","PartnerFunctionCode":"00000004","PartnerNumber":"4223199","PartnerName":"","PartnerFunctionText":"Payer"}],"EmployeeResponsibleNumber":"4031140","PredecessorGUID":null}

至于 OData 服务器实现端,拿到这些数据结构,如何进行处理,这就是后台服务开发的话题了。

具体来说,需要实现接口 /IWBEP/IF_MGW_APPL_SRV_RUNTIME 的 CREATE_DEEP_ENTITY 方法。

更多细节可以参阅 SAP 帮助文档:

https://help.sap.com/docs/SAP_S4HANA_ON-PREMISE/68bf513362174...

以及笔者原创的 OData 开发教程:SAP OData 开发实战教程:从入门到提高


注销
1k 声望1.6k 粉丝

invalid