上一章讲了BDL(Behavior Definition Language) 。
SAP学习笔记 - 开发48 - RAP开发 Managed App BDL(Behavior Definition Language) -CSDN博客
本章继续将RAP开发的知识。
- Mapping
- Behavior Pool Class
- V2 版本的Service Binding (V4 版的需要启用Draft才会显示Create按钮)
- ETag
目录
1-2,mapping for zt04_booking_m
1-3,mapping for zt04_booksuppl_m
2, Behavior Pool Class(RAP Handler Class)
3-1,方法 1:直接在 CDS View 上使用 @odata.draft.enabled
3-2,方法 2:显式使用 @ObjectModel 注解(旧版方式,SAP 推荐使用 @odata 替代)
3-3,方法 3:在 Behavior Definition 中启用 Draft
4,作成 Service Binding - Z04_UI_TRAVEL_M_V2
4-4,Behavior Definition - Z04_DV_Travel_M 去掉Readonly
4-5,Behavior Definition - Z04_DV_Booking_M 去掉Readonly
4-6,Behavior Definition - Z04_DV_BookSuppl_M 去掉Readonly
5-2. ETag 在 SAP Fiori / OData 中的应用
5-4. 如何在 SAP CDS / RAP 中启用 ETag?
(2) 在 Behavior Definition 中启用 ETag 检查
5-8,实战 - 在Data View(Interface层)加ETag
a),Data Definition - Z04_DV_Travel_M - @Semantics.systemDateTime.localInstanceLastChangedAt: true
b),Behavior Definition - Z04_DV_Travel_M - etag master LastChangedAt
c),Data Definition - Z04_DV_Booking_M - @Semantics.systemDateTime.localInstanceLastChangedAt: true
d),Behavior Definition - Z04_DV_Booking_M - etag master LastChangedAt
e),Data Definition - Z04_DV_BookSuppl_M - @Semantics.systemDateTime.localInstanceLastChangedAt: true
f),Behavior Definition - Z04_DV_BookSuppl_M - etag master LastChangedAt
5-9,实战 - 在Projection View(Consumption层)加ETag
5-10,实战 - 前端 ETag 不一致时的Check Error
下面是详细内容。
1,Mapping
Mapping就是下面这个东西,用于匹配View entity 里面的字段和最底层的表里的字段。
为啥需要这个东西呢?
想让Fiori Element(前端UI)输入的数据后端能认,能保存,就需要添加Mapping。
前面咱们在说Data Definition ( Data View /Projection View Entity)里面都是有 as 别名的,
一旦有了别名,那么后续的都要用别名,所以前端看到的很可能和数据库表里不一样。

1-1,mapping for zt04_travel_m
mapping for zt04_travel_m
{
TravelId = travel_id;
AgencyId = agency_id;
CustomerId = customer_id;
BeginDate = begin_date;
EndDate = end_date;
BookingFee = booking_fee;
TotalPrice = total_price;
CurrencyCode = currency_code;
Description = description;
OverallStatus = overall_status;
CreatedBy = created_by;
CreatedAt = created_at;
LastChangedBy = last_changed_by;
LastChangedAt = last_changed_at;
}
1-2,mapping for zt04_booking_m
mapping for zt04_booking_m
{
TravelId = travel_id;
BookingId = booking_id;
BookingDate = booking_date;
CustomerId = customer_id;
CarrierId = carrier_id;
ConnectionId = connection_id;
FlightDate = flight_date;
FlightPrice = flight_price;
CurrencyCode = currency_code;
BookingStatus = booking_status;
LastChangedAt = last_changed_at;
}
1-3,mapping for zt04_booksuppl_m
mapping for zt04_booksuppl_m
{
TravelId = travel_id;
BookingId = booking_id;
BookingSupplementId = booking_supplement_id;
SupplementId = supplement_id;
Price = price;
CurrencyCode = currency_code;
LastChangedAt = last_changed_at;
}
TODO:怪了,怎么还没有Create 按钮呢??

2, Behavior Pool Class(RAP Handler Class)
啥是 Behavior Pool 呢?
Behavior Pool Class 是 SAP Fiori Elements 和 RAP (Restful ABAP Programming) 模型中的一个重要概念,主要用于定义和实现业务对象的行为。
2-1,主要用途
-
集中管理业务逻辑:作为业务对象行为的集中存储库,包含所有与业务实体相关的行为实现。
-
定义标准操作:实现标准 CRUD 操作(Create, Read, Update, Delete)的自定义逻辑。
-
实现附加功能:包括:
-
验证逻辑(Validations)
-
授权检查(Authorizations)
-
确定逻辑(Determinations)
-
动作(Actions)
-
特性控制(Feature Control)
-
-
提高代码复用:通过继承机制,多个业务实体可以共享相同的行为实现。
2-2,典型应用场景
-
覆盖标准操作(如自定义保存逻辑)
-
实现业务特定的验证规则
-
定义实体间的交互行为
-
控制UI元素的可见性和可用性
2-3,技术特点
-
使用 ABAP 类实现(通常继承自标准行为池类)
-
通过注解或配置与 CDS 视图关联
-
在 RAP 框架中自动调用
Behavior Pool Class 是连接数据模型(CDS)和用户界面(Fiori Elements)的关键组件,使开发者能够在不修改UI框架的情况下定制业务逻辑。
下面在咱们的系统上建几个空的Behavior Pool Class。
2-4,zcl_bp_04_dv_travel_m

这里暂时啥也没有,咱们就是单纯的作成一个Class,将来有些实现可以放到这里来做

2-5,zcl_bp_04_dv_booking_m


2-6,zcl_bp_04_dv_booking_m


3,为啥Create按钮没显示出来?
查了半天,原因好像是OData V4,必须要启用 draft,才会显示该Create按钮/ Edit按钮也一样。
>With OData V4, create button becomes visible only if you enable draft.
Create button not visible - SAP Community
Solved: CAP Node.js Create Button missing in Odata preview - SAP Community
还有人问说那必须启用Draft功能了啊?我能不启用不?
好像不能,如果你实在不想用Draft功能,那你用V2嘛,它不强制你启用Draft。
那要如何启用Draft功能呢?
SAP CDS 提供了 @ 注解语法,可以直接在 CDS 视图上添加 OData 注解。
3-1,方法 1:直接在 CDS View 上使用 @odata.draft.enabled
在 CDS View 的 DEFINE VIEW 或 ENTITY 定义上,你可以直接添加 @odata.draft.enabled: true 来启用 Draft 模式:
abap
@AbapCatalog.sqlViewName: 'ZBOOKS'
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Books'
@odata.draft.enabled: true
define view ZBooks as select from book as Book {
key Book.id as Id,
Book.title as Title,
Book.author as Author,
Book.price as Price
}
📌 注意:
@odata.draft.enabled是 SAP 推荐的 CDS 原生注解,它会自动转换为 OData 的Common.DraftRoot或Common.DraftNode注解。
3-2,方法 2:显式使用 @ObjectModel 注解(旧版方式,SAP 推荐使用 @odata 替代)
如果你使用的是较旧的 SAP 版本,可能会看到 @ObjectModel 注解方式:
abap
@AbapCatalog.sqlViewName: 'ZBOOKS'
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Books'
@ObjectModel.modelCategory: #BUSINESS_OBJECT
@ObjectModel.writeActivePersistence: 'ZBOOK_DB'
@ObjectModel.draftRootEnabled: true
define view ZBooks as select from book as Book {
key Book.id as Id,
Book.title as Title,
Book.author as Author,
Book.price as Price
}
⚠️ 注意:
@ObjectModel注解方式在较新的 SAP BTP / RAP 开发中已被@odata替代,但仍然可用。
3-3,方法 3:在 Behavior Definition 中启用 Draft
如果你使用 ABAP RESTful Application Programming (RAP),还需要在 Behavior Definition 里启用 Draft:
abap
managed implementation in class ZBP_BOOKS unique;
strict ( 2 );
define behavior for ZBooks alias Books
// 启用 Draft 支持
draft table ZBOOKS_DRAFT
lock master
authorization master ( instance )
{
// 定义操作
create;
update;
delete;
}
📌 关键点:
draft table ZBOOKS_DRAFT表示 Draft 数据存储的表(需要提前创建)。必须定义
create,update,delete操作,否则 Draft 功能可能无法正常工作。
3-4,总结
| 方式 | 适用场景 | 代码示例 |
|---|---|---|
CDS @odata.draft.enabled | 推荐方式(SAP BTP / RAP) | @odata.draft.enabled: true |
CDS @ObjectModel.draftRootEnabled | 旧版方式(兼容性) | @ObjectModel.draftRootEnabled: true |
| Behavior Definition | RAP 必须配置 | draft table ZBOOKS_DRAFT |
如果你的项目是 SAP Fiori Elements + RAP,建议:
-
在 CDS View 上使用
@odata.draft.enabled: true -
在 Behavior Definition 里配置
draft table -
不需要额外写 Metadata Extension(除非有特殊 UI 注解)
这样就能完整支持 Draft 功能了! 🚀
我合计这里是RAP,那咱们用上面 方法3 不就OK了吗?
结果我发现 draft table ZBOOKS_DRAFT,这个Draft 用Table要单独做。
那倒也是,草稿嘛,虽然是临时数据,也是数据啊,总得有地方存嘛。
TODO:那就先这样,以后再说。
上面V4 需要启用Draft 才会显示Create按钮,等学到Draft的时候再回归V4。
这里咱为了实验作成/编集,咱们这里先用一下不受推荐的 V2。
4,作成 Service Binding - Z04_UI_TRAVEL_M_V2
作成方法参照如下文章,作成完之后,点一下Publish 发布服务
SAP学习笔记 - 开发45 - RAP开发 Managed App New Service Definition,Metadata Extension-CSDN博客

4-1,Create - Travel_M
然后再Preview,这回就显示 Create(登录)了吧。

点作成按钮
TODO:这个Travel ID咋还不能输入了呢?

先输入其他字段值,然后点作成(Save)

Travel_M 数据看来是作成成功了

4-2,Create - Booking_M
点Booking 一览 的 Create(作成)按钮

输入各字段值,点 作成按钮

这样就作成了

4-3,Create - BookSuppl_M
咱们再点 Booking Supplement 一览的作成按钮

输入各字段值,然后点作成按钮

这个也作成好了

看一下数据,作成的是Travel ID 是 00000000
看页面,应该就是这条数据了哈

ID 有点儿怪哈,我再做几条试试看。
出错了,说Key重复,可见这个Travel ID什么的,应该也要可以输入的吧

下面来看一下如何修改成可以手动输入Key。
4-4,Behavior Definition - Z04_DV_Travel_M 去掉Readonly

然后再试试,好像就好了哈

好,输入,点 作成

这不就作成了嘛

4-5,Behavior Definition - Z04_DV_Booking_M 去掉Readonly
但是注意这里的Travel ID必须要设为Readonly,因为咱们和Travel_M设置了父子关系了嘛

如此就可以输入Booking ID了

4-6,Behavior Definition - Z04_DV_BookSuppl_M 去掉Readonly
但是注意这里的Travel ID/Booking ID 必须要设为Readonly,因为咱们和Booking_M设置了父子关系了嘛,而且为了数据的连贯性,Travel ID也不能让手动改,都保持Readonly。
这样改一下,Booking Supplement ID 也就可以改了哈。

做完数据之后,然后回到一览,这回就完事儿OK了吧。

5,ETag
咱们先看一下ETag是啥,和干啥用的。
ETag(实体标签)是 HTTP 协议 和 OData 服务 中用于 资源版本控制 的机制,主要用于 乐观锁(Optimistic Locking),防止并发修改导致的数据冲突。
5-1. ETag 的作用
-
检测资源是否被修改:客户端请求数据时,服务器返回 ETag(通常是哈希值或版本号),客户端后续修改数据时需带上该 ETag,服务器会检查 ETag 是否匹配,如果不匹配则拒绝更新(返回
412 Precondition Failed)。 -
减少不必要的数据传输:客户端可通过
If-None-Match头(携带 ETag)询问服务器资源是否变化,若无变化,服务器返回304 Not Modified,节省带宽。
5-2. ETag 在 SAP Fiori / OData 中的应用
在 SAP Fiori Elements 和 OData 服务 中,ETag 通常用于:
-
防止并发修改:多个用户同时编辑同一条数据时,只有第一个提交的能成功,后续提交会因 ETag 不匹配而失败。
-
支持 Draft(草稿)模式:在 RAP(ABAP RESTful Application Programming)中,ETag 确保草稿和激活的实例版本一致。
5-3. ETag 的生成方式
ETag 的值通常由服务器生成,可以是:
-
数据库记录的
last_changed_timestamp -
哈希值(如 MD5、SHA1)
-
自定义版本号(如 UUID 或递增数字)
在 SAP CDS / RAP 中,ETag 通常基于 @odata.etag 注解 定义的字段自动生成。
5-4. 如何在 SAP CDS / RAP 中启用 ETag?
(1) 在 CDS View 中定义 ETag 字段
abap
@AbapCatalog.sqlViewName: 'ZBOOKS'
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Books'
@odata.draft.enabled: true
define view ZBooks as select from book as Book {
key Book.id as Id,
Book.title as Title,
Book.author as Author,
Book.price as Price,
// 定义 ETag 字段(通常用最后修改时间或版本号)
Book.last_changed as LastChanged
// 使用 @odata.etag 注解标记该字段用于 ETag
@odata.etag: true
}
📌 说明:
last_changed可以是UTCLONG类型(时间戳),每次数据修改时自动更新。
(2) 在 Behavior Definition 中启用 ETag 检查
abap
managed implementation in class ZBP_BOOKS unique;
strict ( 2 );
define behavior for ZBooks alias Books
draft table ZBOOKS_DRAFT
lock master
authorization master ( instance )
{
// 启用 ETag 检查(乐观锁)
use etag;
// 定义操作
create;
update;
delete;
}
5-5. ETag 的工作流程(示例)
-
客户端请求数据:
http
GET /odata/v4/AdminService/Books(1)
服务器返回:
http
-
HTTP/1.1 200 OK ETag: "2024-05-20T14:30:00Z" { "ID": 1, "Title": "SAP RAP Guide", "Author": "John Doe", "Price": 49.99 } -
客户端尝试修改数据(携带 ETag):
http
-
PATCH /odata/v4/AdminService/Books(1) If-Match: "2024-05-20T14:30:00Z" { "Price": 59.99 }-
如果 ETag 匹配 → 更新成功(返回
200 OK)。 -
如果 ETag 不匹配(数据已被其他人修改)→ 返回
412 Precondition Failed。
-
5-6. 常见问题
Q1: 如果不加 ETag 会怎样?
-
数据可能被覆盖:多个用户同时编辑时,后提交的会覆盖先提交的修改("last write wins")。
-
Fiori App 可能报错:某些 SAP Fiori Elements 应用(如 Object Page)要求必须启用 ETag。
Q2: ETag 和 Draft 模式有什么关系?
-
在 Draft 模式 下,ETag 用于确保:
-
用户编辑的是最新的草稿版本。
-
激活操作时检查数据未被其他人修改。
-
Q3: 能否自定义 ETag 生成逻辑?
-
可以,通过 Behavior Implementation 类中的
get_etag方法自定义:abap
-
CLASS zbp_books DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF zbooks. PUBLIC SECTION. METHODS get_etag REDEFINITION. ENDCLASS. CLASS zbp_books IMPLEMENTATION. METHOD get_etag. " 自定义 ETag 计算逻辑(如 MD5 哈希) etag = compute_custom_etag( keys ). ENDMETHOD. ENDCLASS.
5-7.总结
| 关键点 | 说明 |
|---|---|
| ETag 的作用 | 乐观锁机制,防止并发修改冲突 |
| SAP 中的实现 | 通过 @odata.etag 注解 + Behavior Definition 的 use etag |
| Draft 模式依赖 ETag | 确保草稿和激活版本的一致性 |
| 客户端交互 | 通过 If-Match 请求头传递 ETag |
如果你的 SAP Fiori Elements 应用涉及 数据编辑,强烈建议启用 ETag 以避免数据竞争问题! 🚀
下面来看一下实例。
5-8,实战 - 在Data View(Interface层)加ETag
a),Data Definition - Z04_DV_Travel_M - @Semantics.systemDateTime.localInstanceLastChangedAt: true

b),Behavior Definition - Z04_DV_Travel_M - etag master LastChangedAt
这个和上面的 a 是配套的。

c),Data Definition - Z04_DV_Booking_M - @Semantics.systemDateTime.localInstanceLastChangedAt: true

d),Behavior Definition - Z04_DV_Booking_M - etag master LastChangedAt
这个和上面的 c 是配套的。

e),Data Definition - Z04_DV_BookSuppl_M - @Semantics.systemDateTime.localInstanceLastChangedAt: true

f),Behavior Definition - Z04_DV_BookSuppl_M - etag master LastChangedAt
这个和上面的 e 是配套的。

上面在Data Definition(Interface层)上加了ETag,是不是就完事儿了呢?
不是的,在Data Definition(Interface层)之上,还有一层Projection View(Consumption层),
那里 不加也是不好用的。
咱们在Projection View里面也加一下,然后看一下在前端的表现形式。
5-9,实战 - 在Projection View(Consumption层)加ETag
Projection View里面就简单了,只需加 use etag即可。

按下 Ctrl+F3 激活,然后刷新 V2 版的Preview

点编集,然后点F12 > Network Tab
就是这样的,修改任意字段,然后点一下保存按钮
就是这个If-Match,它后面的长长的那个串,就是LastChangedAt 的值,咱们就是用它做ETag的
> If-Match: W/"'SADL-202507231327073360130C~20250723132707.3360130'"

这样ETag就算是准备好了,咱们来看一下如果ETag不一致的时候,会发生什么事儿。
5-10,实战 - 前端 ETag 不一致时的Check Error
打开2个相同的Travel Detail Browser Tab,分别点编集按钮
- Tab1,当然这个也可以理解为User 1,因为谁会没啥事儿打开俩Tab啊,多数时俩User同时编集

- Tab2
- Save Tab1 的内容

- Save Tab2 的内容,显示如下错误,基本上达到了咱们的目的
无法保存您的更改。有较新版本可用。请刷新您的数据,以使更改生效到最新版本。
変更を保存できませんでした。より新しいバージョンがあります。最新バージョンに変更を加えるには、データをリフレッシュしてください。
Your changes could not be saved. A newer version is available. Please refresh your data to make your changes to the latest version.

咱们直接点 Refresh 按钮,这样就可以显示最新数据
然后再点编集按钮,再最新的基础上修改
然后点保存,就OK了
以上就是本篇的全部内容。
更多SAP顾问业务知识请点击下面目录链接或东京老树根的博客主页


1万+

被折叠的 条评论
为什么被折叠?



