一、概念
以个人图书管理为例,创建一个ABAP RESTful 应用程序编程模型项目。最终要实现的效果:
- 用于管理书籍的程序。
- 读取、修改和删除书籍。
二、Data Model-数据模型
2.1 创建项目基础数据库表
首先,创建一个图书相关的表,点击新建-选择Database Table,填写表的名称和描述。如果正式项目,点击下一步,选择请求号,这里为demo,不选择,点击完成即可。
保存后,通过SAPGUI打开表,维护表字段
向数据库表添加字段,然后激活数据库表
2.2 创建 CDS 视图实体。
View模型,选择 root CDS view entity 根实体是 ABAP RESTful 应用程序编程模型项目的主要业务对象,其他一切都以它为基础进行功能延伸。
更改CDS 中代码为下面所示
@AccessControl.authorizationCheck:#NOT_REQUIRED
@EndUserText.label:'CDS Entity - Books'
Define root view entity ZRAP_IV_BOOKS as select from zrap_books
{Key book_guid as BookGuid,isbn as ISBN,title as Title,genre as Genre,author as Author,
book_pagesasBookPages,
descriptionasDescription,
purch_dateasPurchasingDate,//为purch_date 定义别名为purchasingDate
finishedasReadingFinished,
ratingasRating,
noteasNote
}
三、Behavior Definition 核心数据服务:行为定义
若要指定业务对象的行为,可以创建与上一步中创建的根视图实体相对应的行为定义。行为定义设置实现类型大家可以deepseek一下,网上的概念相关的内容比较多了,这里不赘述。
选择CDS Entity,创建对象行为,类型选择Manage(托管)
代码如下:
managed;// implementation in class zbp_rap_iv_books unique;
Define behavior for ZRAP_IV_BOOKS//alias <alias_name>
Persistent table ZRAP_BOOKS
lockmaster
//authorization master ( instance )
//etag master <field_name>
{
create;
update;
delete;
Mapping for ZRAP_BOOKS corresponding{
BookGuid=book_guid;
PurchasingDate=purch_date;
BookPages=book_pages;
ReadingFinished=finished;
}
}
对于CDS视图创建的行为定义,我们引用了数据库数据表ZRAP_BOOKS。需要为托管方案中的每个根视图设置 lock master 关键字。然后,我们通过取消注释来启用创建、更新和删除函数。对于与持久性表中的字段名称不同的每个 CDS 字段,还需要字段映射,因此在CDS 数据定义中提供字段别名时请记住这一点。然后保存和激活行为定义。
四、Projection Views-投影视图
现在,我们将 ABAP RESTful 应用程序编程模型架构中的一层上移到业务服务供应层。这一层是特定于应用程序的,这意味着我们可以根据特定应用程序的需求对数据模型进行更改。Projection View 是ABAP 数据字典中的一种视图类型,用于从数据库表中筛选特定字段(类似数据库中的"投影"操作)。它通过隐藏非必要字段简化表结构,常用于接口或权限控制场景。
举个权限管理相关的例子说明一下,如果我们有三个用于管理书籍的应用程序:一个用于管理员的应用程序,一个用于支持用户,另一个用于最终用户。其中每个应用程序都需要相同的基本模型,但需要不同的操作,启用不同的 CRUD 操作,并且应授予不同的权限。由于已经定义了基本模型,我们现在创建投影视图,使 CDS 数据定义的字段仅可用于此方案中真正需要的进一步使用。通过创建投影视图(Projection View),可以限制对敏感字段的访问。
第一步,选择新建一个Projection View,参考root view
我们将一个新的根视图实体定义为基本数据定义的投影,并使所有字段都可供使用。此外,我们还使用注解 Metadata.allowExtensions: true 来允许使用 CDS 元数据扩展,我们将在后面的步骤来创建该扩展。现在保存并激活新的投影视图。代码如下:
@EndUserText.label:'CDS Projection - Books'
@AccessControl.authorizationCheck:#NOT_REQUIRED
@Metadata.allowExtensions:true
Define root view entity ZRAP_CV_BOOKS as projectionon ZRAP_IV_BOOKS
{
Key BookGuid,ISBN,Title,Genre,Author,BookPages,Description,PurchasingDate,ReadingFinished,Rating,Note
}
这个时候,我们还需要对基本行为定义进行投影,使该行为仅可用于此方案真正需要的行为。我们通过右键单击投影视图,如下图选择“新建行为定义”,然后输入以下信息来创建这样的行为投影:
代码:
projection;
Define behavior for ZRAP_CV_BOOKS//alias <alias_name>
{use create;use update;use delete;
}
在我们的例子中,应该可以在我们的消费者端使用创建、更新和删除。由于我们在行为定义中提供了这些函数,因此它们也可以在行为投影中使用。现在缺少的最后一层是服务消费层。
五、Service Definition and Service Binding-服务定义和服务绑定
5.1 服务定义
若要使业务对象成为 OData 服务的一部分,需要创建两个对象:服务定义和服务绑定。完成此操作后,我们需要添加注释。服务定义定义应属于 OData 服务的所有投影视图和其他 CDS 数据定义。另一方面,服务绑定将 OData 协议绑定到服务定义,使其成为 OData 服务。
要创建服务定义,请右键单击我们的投影视图,然后选择 New Service Definition,参考下图。
代码如下,激活代码。
5.2服务绑定
现在需要通过创建服务绑定将 OData 协议绑定到服务定义。右键单击服务定义,然后选择 New Service Binding。然后,如下图所示创建 OData V4 服务,这样在开发 SAP Fiori 元素应用程序中可以使用(下一篇写部署Firoi应用的时候举例说明):
OData 服务需要注册并发布到 Internet 通信框架 (ICF) 节点 /sap/opu/odata 中的 SAP 网关上。对于 OData V2 服务,可以使用“发布”按钮从服务绑定自动完成此操作。但是,使用 OData V4 服务时,需要通过事务 /IWFND/V4_ADMIN(SAP 网关服务管理)手动注册这些服务。参考:SAP Note 3101976 。
SAP 网关提供两个用于维护和管理 SAP 网关服务的事务:OData V2 的事务 /IWFND/MAINT_SERVICE(激活和维护服务)和 OData V4 服务的事务 /IWFND/V4_ADMIN(SAP 网关服务管理)。使用这些事务,可以注册和维护 OData 服务,并且可以从这些服务访问错误日志 (Transaction /IWFND/ERROR_LOG) 等其他功能。如果服务/系统别名指向远程函数调用(RFC) 连接,则还可以在此处实现前端服务器上的 OData 终结点与包含实现逻辑的后端服务器之间的链接。
可以执行事务代码:/IWFND/V4_ADMIN 发布服务,
或者在ADT 环境直接发布。
发布服务后,在ADT中可以预览服务,显示为空的内容。这是因为还没有添加批注-Annotations
5.3 添加批注
为了更改当前的 UI,我们将使用 CDS 元数据扩展来定义 CDS 注释。使用这些扩展文件,与 UI 界面显示相关的注释将与 CDS 数据定义文件隔离开,使其在其他 SAP 系统中可覆盖,在这些系统中,我们的CDS代码不应被修改,而是被扩展。通过右键单击投影视图并在上下文菜单中选择“新建元数据扩展”来创建新的 CDS 元数据扩展。
代码如下:
@Metadata.layer:#CUSTOMER
@UI.headerInfo:{
typeName:'Book',
typeNamePlural:'Books',
title.value:'Title',
description.value:'ISBN'
}
Annotate view ZRAP_CV_BOOKS
with
{
@UI.hidden:true
BookGuid;
@EndUserText.label:'ISBN号'
@UI.lineItem:[{position:10,importance:#HIGH}]
@UI.selectionField:[{position:10}]
ISBN;
@EndUserText.label:'标题'
@UI.lineItem:[{position:20,importance:#HIGH}]
@UI.selectionField:[{position:20}]
Title;
@EndUserText.label:'性别'
@UI.lineItem:[{position:40,importance:#MEDIUM}]
@UI.selectionField:[{position:20}]
Genre;
@EndUserText.label:'作者'
@UI.lineItem:[{position:30,importance:#MEDIUM}]
Author;
@EndUserText.label:'阅读完成日期'
@UI.lineItem:[{position:50,importance:#LOW}]
ReadingFinished;
@UI.lineItem:[{
label:'等级',
valueQualifier:'Rating',
type:#AS_DATAPOINT,
position:60,
importance:#LOW
}]
@UI.dataPoint:{
targetValue:5,
visualization:#RATING
}
Rating;
}
注解 @UI.headerInfo 负责我们应用程序的表格和详细信息标题。通过添加 @UI.lineItem 注释,可以定义 SAP Fiori 元素列表报表应用程序的列,并且 @UI.selectionField 注释将选择字段添加到筛选器栏。再执行服务,效果如下:
现在,为了能够创建新条目,需要在业务数据录入过程中启用草稿处理,在服务绑定中使用了OData V4与ODATA V2有个区别,则如下所示,可以直接创建。
六、Draft Handling-草稿处理
草稿是业务对象实体的临时版本。其数据可能不一致或尚未完成,但仍必须随时存储,而不会干扰业务对象的持久活动版本。此功能可最大程度地降低由于技术或人为错误而导致的数据丢失风险。可以在不同的设备上暂停和重新启动恢复草稿工作,通过为业务对象启用草稿处理,我们可以存储和使用对象的临时版本,而不会干扰持久性数据。草稿处理可用于托管或非托管开发方法,但存在一些差异:
Managed draft handling:托管草稿处理草稿处理不会对验证程序或确定产生直接影响,但如果使用的是 OData V4,则必须为 SAP Fiori 元素激活草稿处理,以提供创建和删除功能。
Unmanaged draft handling:非托管草稿处理使用非托管行为时,只有在启用草稿处理时,确定和验证才有效。若要启用草稿处理,我们还需要首先探讨并发控制。然后,我们可以继续讨论草稿操作以及如何更新和创建字段控件。
6.1 并发控制
并发控制可防止并发使用相同的数据库条目,以避免数据不一致。ABAP RESTful 应用程序编程模型中提供了两个并发控制概念,如下所示:
Pessimistic concurrency control
悲观并发控制悲观并发可防止多个用户同时修改数据库条目。这是指经典的独有 ABAP 锁定和排队技术,并与ABAP 会话相关联。此控件需要以非托管方法实现,但这由ABAP RESTful 应用程序编程模型在托管方法中处理。Pessimistic悲观控制始终是默认的并发控制。
Optimistic concurrency control
乐观并发控制乐观并发控制基于实体标记(ETag)字段,该字段是指在特定时间标识条目的特定值。在 ABAP RESTful 应用程序编程模型中,这通常是通过使用引用上次更改条目的时间的时间戳来完成的。这仅在 OData 使用方案中相关,因为这将随每个请求一起发送,防止用旧数据替代新数据,并且完全由 ABAP RESTful 应用程序编程模型框架处理。
在我们的例子中,我们将使用乐观的方法。因此,我们将向实体添加一些新字段,主要用于维护谁更改了条目、何时更改、谁创建了条目以及何时创建条目。将下列的字段添加到数据库表 ZRAP_BOOKS 中,然后重新激活它。
向CDS Entity view 和 projection view添加字段
在元数据扩展中使用注释UI.hidden: true 对用户隐藏这些字段。
然后就是处理视图的行为定义,将 ETag 处理和字段映射添加到我们的行为定义中。
使用带有草稿功能,还需要指定一个草稿表缓存数据,这可以通过为带有关键字draft table 的新数据库表提供名称来完成。使用快速修复 Quick Fix可自动生成草稿表。
此表的结构与我们的 CDS 视图相同,但具有附加的草稿管理字段。我们还通过添加关键字 total etag 和 etag master 来引用新添加的数据库表字段,从而添加了乐观并发控制。ABAP RESTful 应用程序编程模型会自动检查和维护这些值。此外,还必须将新的视图字段添加到映射中。
6.2 Draft Actions-草稿操作
现在,我们需要指定哪些草稿操作应该可用,如下所示:
- Edit: 编辑将业务对象的活动版本复制到草稿表中。
- Activate: 激活激活草稿条目并调用“准备”操作。这是要编辑的反向类型。
- Discard:“放弃”将删除草稿。
- Prepare:准备执行为此步骤定义的确定和验证。在草稿成为持久性数据库表中的活动版本之前,会直接调用它。
- Resume:“恢复”(Resume) 允许您继续处理草稿。
在我们的例子中,我们将在行为定义中使用所有这些草稿操作:
在行为映射中中映射草稿处理。
刷新服务,发现有创建按钮,点击可以创建新的条目数据。
PS: ODATA V4 与ODATA V2 发生一些变化,草稿状态不再显示
因为创建的页面维护的字段内容没有定义,所以需要先定义字段,在View 的metadata extension中定义。通过添加新的 UI.facet 注释,我们可以在对象页面中创建部分。我们在标记为“YOURBOOK”的常规部分中添加了两个标记为“GENERAL”和“READING”的子部分,每个子部分都包含 CDS 视图的不同字段,这些字段与 UI.fieldGroup 或 UI.identification 注释相关联。
代码:
@Metadata.layer:#CUSTOMER
@UI.headerInfo:{
typeName:'Book',
typeNamePlural:'Books',
title.value:'Title',
description.value:'ISBN'
}
Annotate view ZRAP_CV_BOOK S with
{
@UI.facet:[{
id:'YOURBOOK',
type:#COLLECTION,
position:10,
label:'Your Book'
},{
id:'GENERAL',
type:#IDENTIFICATION_REFERENCE,
parentId:'YOURBOOK',
label:'General Information'
},{
id:'READING',
type:#FIELDGROUP_REFERENCE,
parentId:'YOURBOOK',
targetQualifier:'READFAC',
label:'Reading Information'
}]
@UI.hidden:true
BookGuid;
@EndUserText.label:'ISBN号'
@UI.lineItem:[{position:10,importance:#HIGH}]
@UI.selectionField:[{position:10}]
@UI.identification:[{position:10}]
ISBN;
@EndUserText.label:'标题'
@UI.lineItem:[{position:20,importance:#HIGH}]
@UI.selectionField:[{position:20}]
@UI.identification:[{position:20}]
Title;
@EndUserText.label:'性别'
@UI.lineItem:[{position:40,importance:#MEDIUM}]
@UI.selectionField:[{position:20}]
@UI.identification:[{position:30}]
Genre;
@EndUserText.label:'作者'
@UI.lineItem:[{position:30,importance:#MEDIUM}]
@UI.identification:[{position:40}]
Author;
@EndUserText.label:'Pages'
@UI.identification:[{position:50}]
BookPages;
@EndUserText.label:'Description'
@UI.identification:[{position:60}]
Description;
@EndUserText.label:'Purchasing Date'
@UI.identification:[{position:10}]
PurchasingDate;
@EndUserText.label:'阅读完成日期'
@UI.lineItem:[{position:50,importance:#LOW}]
@UI.fieldGroup:[{qualifier:'READFAC',position:10}]
ReadingFinished;
@UI.lineItem:[{
label:'等级',
valueQualifier:'Rating',
type:#AS_DATAPOINT,
position:60,
importance:#LOW
}]
@UI.dataPoint:{
targetValue:5,
visualization:#RATING
}
@UI.fieldGroup:[{label:'Your Rating',qualifier:'READFAC',valueQualifier:'Rating',type:#AS_DATAPOINT,position:20}]
Rating;
@EndUserText.label:'Notes'
@UI.fieldGroup:[{qualifier:'READFAC',position:30}]
Note;
@UI.hidden:true
ChangedAt;
@UI.hidden:true
ChangedBy;
@UI.hidden:true
CreatedAt;
@UI.hidden:true
CreatedBy;
@UI.hidden:true
TotalChangedAt;
}
点击创建按钮:
6.2 Update and Create Field Control-更新和创建字段控件
要使 ABAP RESTful 应用程序编程模型能够知道哪些字段应该在哪种模式下进行维护,最后要做的就是启用静态字段控制和托管编号。
ABAP RESTful 应用程序编程模型中的编号技术
ABAP RESTful 应用程序编程模型提供了多种方法来设置业务对象主键的值:外部编号、内部编号和可选的外部编号技术。但是,托管编号仅适用于基于 UUID 的主键。让我们更详细地看一下这三种方法:
- 外部编号,意味着客户端负责提供值作为主键。这适用于这两种实现方案。
- 内部编号,意味着 ABAP RESTful 应用程序编程模型计算主键的值。这可以由托管方案中的ABAP RESTful 应用程序编程模型本身完成,也可以由非托管方案中的开发人员完成。
- 可选的外部编号,此编号技术可用于托管方案。如果客户端未发送主键的值,则ABAP RESTful 应用程序编程模型会为他生成一个值。
在我们的例子中,我们让 ABAP RESTful 应用程序编程模型计算主键的 UUID。此外,某些字段应该是必填字段,因此我们需要更新我们的行为定义,如下所示:
现在,我们的 ABAP RESTful 应用程序编程模型项目支持以下功能:
- Draft handling
- Create
- Update
- Delete
- Managed numbering托管编号
- Static field control 静态控制
七、Actions-操作
ABAP RESTful 应用程序编程模型中的操作是业务对象本身的一部分,可以从 OData 或通过 ABAP 调用。这些操作被定义为非标准修改操作,它们有三种不同的特殊类型:
- Internal actions-内部操作
内部操作只能从行为实现中调用,并且可以视为私有操作。
- Static actions-静态操作
静态操作不直接绑定到业务对象的实例,而是绑定到整个实体范围。
- Factory actions-工厂操作
工厂操作可用于创建具有预定义值的新条目,例如,如果要复制现有条目。
必须使用 action 关键字在业务对象的行为定义中定义操作。然后,必须在行为实现中实现操作的逻辑。默认情况下,操作始终绑定到业务对象的单个实例,但可以使用其中一种特殊类型进行更改。此外,操作可以具有输入参数(包含键)和一个结果参数。操作在 OData 中作为函数导入提供,可以使用实体操作语言(EML-Entity Manipulation Language )在 ABAP 中访问。在我们的示例中,我们将添加一个名为 finishBook 的实例操作,该操作会将持久表中的 finished 标志设置为true。然后,这将预配到预配层,并使用注释在 SAP Fiori 元素预览中进行访问。
EML 是一组新的 ABAP 语句,用于授予对 ABAP RESTful 应用程序编程模型业务对象的访问权。EML 可用于读取、修改或执行对业务对象的操作,以及触发持久性存储。
EML 使用派生数据类型作为参数来传递数据、接收结果和发送消息。它们是针对特定业务对象量身定制的,不仅提供必要的业务对象数据,还提供组件的更多信息。EML 提供以下方法:
- READ ENTITY
READ ENTITY is used to read an ABAP RESTful application programming model business object based on its primary keys.
READ ENTITY READ ENTITY 用于根据 ABAP RESTful 应用程序编程模型业务对象的主键读取其主键。 - MODIFY ENTITY
MODIFY ENTITY is used to modify a business object and its data. It has the following subtypes:
MODIFY ENTITY MODIFY ENTITY 用于修改业务对象及其数据。它具有以下亚型:- MODIFY ENTITY CREATE: Creates new entries.
MODIFY ENTITY CREATE:创建新条目。 - MODIFY ENTITY UPDATE: Updates existing entries.
MODIFY ENTITY UPDATE:更新现有条目。 - MODIFY ENTITY DELETE: Deletes existing entries.
MODIFY ENTITY DELETE:删除现有条目。
- MODIFY ENTITY EXECUTE: Executes an action.
MODIFY ENTITY EXECUTE:执行操作。
- MODIFY ENTITY CREATE: Creates new entries.
首先,让我们在行为定义中定义一个动作 finishBook,我们还在类中添加了关键字 managed implementation,以添加新的行为池,包括负责业务对象行为实现的本地处理程序类。
保存激活行为定义后,使用对类名和操作的quick fix 操作,我们可以生成行为池和操作的实现。如下,我们现在有一个相对空的本地处理程序类(参见3),只包含操作 finishBook。
在类实现和方法 finishBook 中,我们将实现操作的逻辑。使用 EML 通过提供的键读取业务对象实例,我们希望将字段 ReadingFinished 设置为 true。
为了让投影层projection layer知道并使用这个动作,我们需要在行为投影behavior projection中使用它
最终效果如下: