上一章讲了 建Travel_M 表/Booking_M表/BookSuppl_M表,以及表间关系(Parent-Child)设定。
本章继续学习RAP开发的知识 - 建 Projection View。
在 Data Model View ( CDS View for BO Structure )基础上创建 Projection View ( CDS View for BO Projection )。
难点在于 Provider Contract,需要用 redirected to composition child / redirected to parent来理清它们之间的关系。
目录
1-1,New Data Definition - Travel_M (Projection View)
1-2,New Data Definition - Booking_M (Projection View)
1-3,New Data Definition - BookSuppl_M (Projection View)
下面是详细内容。
1,CDS View for Projection
上一章咱们把CDS View for BO Structure (也就是 data view entity)建好了。
在此基础上,咱们来做 Projection View。

1-1,New Data Definition - Travel_M (Projection View)
Projection View的建法,其实和Data Model View一样,就是选不同模板嘛,其他都一样。

输入Name,Description,Referenced Object,点Next
选TR,点Next
选 Projection View > defineProjectionView,然后点Finish
- 出了个错,说缺 root keyword,那就加呗
ROOT keyword missing in "Z04_PV_TRAVEL_M", since "Z04_DV_TRAVEL_M" has the root property
- 然后又来了个警告,说是缺 Transactional Provider Contract,也加上
Transactional Provider Contract expected for Projection View Z04_PV_Travel_M.

这里深入看一下Provider Contract:
在 SAP RAP (ABAP RESTful Application Programming Model) 中,Provider Contract 定义了 OData 服务如何暴露实体(Entities)的行为和功能。transactional_query 是其中一种 Provider Contract 类型,主要用于支持事务性查询。以下是详细说明:
a. Provider Contract 的主要选项
RAP 中常见的 Provider Contract 选项包括:
| Provider Contract 类型 | 用途 | 适用场景 |
|---|---|---|
transactional_query | 支持在事务中执行查询(允许读操作与后续的 CUD 操作在同一个事务中) | 需要确保查询数据与后续修改在同一事务中(如检查数据后立即更新) |
transactional_interface | 提供完整的事务性 CRUD 操作(Create, Read, Update, Delete) | 标准的业务对象暴露,需支持事务性修改(如主数据维护) |
query | 仅支持只读查询(无事务性修改能力) | 报表、分析类服务,不需要修改数据 |
interface | 仅暴露结构定义(无行为实现),需手动实现行为 | 需要完全自定义行为逻辑时(如特殊校验或复杂处理) |
abstract_entity | 定义抽象实体,供其他实体继承 | 需要复用公共字段或逻辑时(如基类实体) |
b. 关键选项详解
(1) transactional_query
-
作用:
允许在同一个事务中执行查询和后续的修改操作(如先查询数据,再基于结果更新)。 -
示例场景:
-
检查订单状态后立即标记为“已处理”。
-
验证库存数量后扣减库存。
-
-
代码示例:
abap
-
@AccessControl.authorizationCheck: #CHECK @EndUserText.label: 'Transactional Query for Orders' define behavior for ZI_OrderTP transactional query { // 定义查询和操作 }
(2) transactional_interface
-
作用:
提供完整的 CRUD 操作(Create, Read, Update, Delete)及事务支持,是业务对象的默认选择。 -
示例场景:
-
维护客户主数据(创建、修改、删除)。
-
订单管理(支持全生命周期操作)。
-
-
代码示例:
abap
-
define behavior for ZI_CustomerTP transactional interface { // 定义标准操作(create, update, delete, etc.) }
(3) query
-
作用:
仅支持只读查询,无事务性修改能力,性能优于事务性选项。 -
示例场景:
-
销售报表展示。
-
数据分析看板。
-
-
代码示例:
abap
-
define behavior for ZI_SalesReportTP query { // 仅定义查询 }
(4) 其他选项
-
interface:
需手动实现所有行为逻辑(如save_modified、determine_action等),适合高度定制化需求。 -
abstract_entity:
定义公共字段(如created_by、created_at),供其他实体继承。
c. 选择时机与最佳实践
| 需求场景 | 推荐 Provider Contract | 理由 |
|---|---|---|
| 需要查询后立即修改(事务一致性) | transactional_query | 保证查询和修改在同一事务中完成。 |
| 标准业务对象(CRUD 操作) | transactional_interface | 默认选项,支持完整事务性操作。 |
| 只读报表或分析 | query | 无事务开销,性能更高。 |
| 自定义复杂逻辑 | interface | 允许完全手动实现行为。 |
| 实体继承与复用 | abstract_entity | 提取公共字段或逻辑。 |
d. 注意事项
-
性能权衡:
-
事务性选项(如
transactional_query)会带来事务锁开销,只读场景优先用query。
-
-
一致性需求:
-
若需确保查询结果与后续操作的一致性(如避免脏读),必须用
transactional_query。
-
-
OData 暴露:
-
Provider Contract 需与 Service Definition 中的实体暴露方式匹配(如
expose或with)。
-
e. 总结
-
transactional_query:用于需要查询与修改在同一事务中的场景。 -
其他选项根据读写需求(如只读用
query)和事务需求(如完整 CRUD 用transactional_interface)选择。 -
抽象和自定义场景使用
abstract_entity或interface。
同样的,再做一下 Booking_M, BookSuppl_M 的Projection View。
1-2,New Data Definition - Booking_M (Projection View)
这个同样也有下面这个Warning,但是这次做法有点儿不同,不是简单的加一个Provider Contract,而是通过Parent - Child 方式从 Travel_M 进行继承:
>Transactional Provider Contract expected for Projection View Z04_PV_Booking_M.
给 Projection View添加 Parent - Child 关系:
- Parent -> Child >_Booking: redirected to composition child Z04_PV_Booking_M,
- Child -> Parent >_Travel : redirected to parent Z04_PV_Travel_M
然后再Activate,Z04_PV_Booking_M 就不会再出Provider Contract Warning了。
同样的,再做一下 Booking_M, BookSuppl_M 的Projection View。
1-3,New Data Definition - BookSuppl_M (Projection View)
这个同样也有下面这个Warning,做法和Booking_M一样,不是简单的加一个Provider Contract,而是通过Parent - Child 方式从 Booking_M 进行继承:
>Transactional Provider Contract expected for Projection View Z04_PV_BookSuppl_M.
另外,从 BookSuppl_M 看 Travel_M,它俩之间也是有 redirect 关系的,也给加上这层关系:
>_Travel: redirected to Z04_PV_Travel_M

1-4,总结贴一下代码
a),Z04_PV_Travel_M 代码
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Data Definition for Z04_PV_Travel_M - Projection View'
@Metadata.ignorePropagatedAnnotations: true
define root view entity Z04_PV_Travel_M
provider contract transactional_query as projection on Z04_DV_Travel_M
{
key TravelId,
AgencyId,
CustomerId,
BeginDate,
EndDate,
@Semantics.amount.currencyCode: 'CurrencyCode'
BookingFee,
@Semantics.amount.currencyCode: 'CurrencyCode'
TotalPrice,
CurrencyCode,
Description,
OverallStatus,
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt,
/* Associations */
_Agency,
_Booking: redirected to composition child Z04_PV_Booking_M,
_Currency,
_Customer,
_Status
}
b),Z04_PV_Booking_M 代码
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Data Definition for Z04_PV_Booking_M - Projection View'
@Metadata.ignorePropagatedAnnotations: true
define view entity Z04_PV_Booking_M
as projection on Z04_DV_Booking_M
{
key TravelId,
key BookingId,
BookingDate,
CustomerId,
CarrierId,
ConnectionId,
FlightDate,
@Semantics.amount.currencyCode: 'CurrencyCode'
FlightPrice,
CurrencyCode,
BookingStatus,
LastChangedAt,
/* Associations */
_BookingSupplement : redirected to composition child Z04_PV_BookSuppl_M,
_Booking_Status,
_Carrier,
_Connection,
_Customer,
_Travel : redirected to parent Z04_PV_Travel_M
}
c),Z04_PV_BookSuppl_M 代码
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Data Definition for Z04_PV_BookSuppl_M - Projection View'
@Metadata.ignorePropagatedAnnotations: true
define view entity Z04_PV_BookSuppl_M
as projection on Z04_DV_BookSuppl_M
{
key TravelId,
key BookingId,
key BookingSupplementId,
SupplementId,
@Semantics.amount.currencyCode: 'CurrencyCode'
Price,
CurrencyCode,
LastChangedAt,
/* Associations */
_Booking : redirected to parent Z04_PV_Booking_M,
_Supplement,
_SupplementText,
_Travel: redirected to Z04_PV_Travel_M
}
以上就是本篇的全部内容。
更多SAP顾问业务知识请点击下面目录链接或东京老树根的博客主页




1万+

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



