上一章学习了RAP开发的一些知识,Mapping,Behavior Pool Class,ETag。
https://blog.csdn.net/shi_ly/article/details/149477441
本章继续学习RAP的知识 - RAP开发中常用的两个概念,Locking 和 Numbering。
- Locking 是行级锁,不仅是本表,它也会同步锁住关联表的相应行;
- Numbering是自带採番,和Open系中的自增字段还是不一样的。
本章主要是偏理论的,以后再说实战内容。
目录
1-3,Lock的继承/Lock master,Lock dependent
3-1,early numbering - Z04_DV_Travel_M (Behavior Definition)
3-3,RAP开发中,Fiori element里面,derived type是什么?
3-5,earlynumbering_create - 详解
下面是详细内容。
1,Locking
1-1,Locking业务流程
- Update 请求: 由客户端请求到Business Object
- BO会去 Check有没有被Lock
- 如果被Lock的话,就会拒绝该 Update操作
- 如果没被Lock的话,就会设置Lock,然后执行该 Update操作
- 执行Update操作
- 执行完Update操作之后,就会移除该Lock,并返回Response给客户端

1-2,Locking的逻辑流程
- EML Modify:在作成/ 编集页面,入力时并不会Lock 该数据,当点 作成/保存的时候才会Lock
- 如果有 Global Authoritation,那么会先调用它
- 如果由 Lock Implement,那么会先调用它
- 执行 Managed Lock
- 如果是 Unmanaged BO,那么会去调用手写的 Lock 代码

1-3,Lock的继承/Lock master,Lock dependent
比如下图的示例,Travel(父对象)-》Booking(子对象)-》Booking Supplement(孙对象)
那么咱们在Travel上设置 Lock Master,Booking/Booking Supplement上设置Lock dependent,
那么它们三个就变成一个整体了。
- 当Travel表中的某条数据被Lock的时候,对应的Booking/Book Supplement表中的数据也被Lock

Travel_M的 写法就是这个:
lock master

Booking_M,BookSuppl_M 的写法都是这个:
lock dependent by _Travel
注意点:当用 lock dependent 的时候,必须要显式的注明 association,比如
- Booking_M的 association :
- association _Travel;
- BookSuppl_M的 association:
- association _Travel;
- association _Booking;

上面说的是locking 的概念,它实现的是行级锁。
下面说另外一个概念,Numbering,其实对应到SAP里面,就是採番,比如购买发注,受注等等,所有的传票都需要採番,是自带採番,还是手动输入,也是可以Customize的。
咱们这里说的Numbering,相当于是自带採番。
2,Numbering
RAP开发中有 Early Numbering与Late Numbering两种。
在SAP RAP (Restful ABAP Programming) 模型和Fiori Elements开发中,Early Numbering(早期编号)和Late Numbering(延迟编号)是两种处理实体键值生成的策略,它们在业务对象行为(BO Behavior)定义中扮演重要角色。
2-1. Early Numbering(早期编号)
a.用途
-
客户端即时反馈:在数据发送到服务器前就生成键值,提供更流畅的用户体验
-
依赖键值的操作:当后续操作需要依赖已生成的键值时使用
-
乐观锁定场景:在乐观锁定策略下提前建立对象标识
b.使用时机
-
创建新条目时需要立即显示键值
-
当UI需要基于生成的键值执行后续操作时
-
在离线场景或高延迟网络环境下
c.实现方式
在行为定义(BDEF)中:
abap
early numbering;
在行为池(BEHAVIOR POOL)中实现方法:
abap
METHODS earlynumbering FOR NUMBERING
IMPORTING entities FOR CREATE <entity_name>.
2-2. Late Numbering(延迟编号)
a.用途
-
服务器端生成键值:由数据库或业务逻辑决定最终键值
-
复杂键生成逻辑:当键值生成需要访问服务器端数据或复杂逻辑时
-
数据库序列依赖:当键值依赖于数据库序列或触发器时
b.使用时机
-
键值需要从数据库序列获取
-
键值生成需要复杂业务逻辑
-
不要求客户端立即知道键值
-
需要确保键值唯一性的严格场景
c.实现方式
在行为定义(BDEF)中:
abap
late numbering;
在行为池(BEHAVIOR POOL)中实现方法:
abap
METHODS latenumbering FOR NUMBERING
IMPORTING entities FOR CREATE <entity_name>.
2-3. 对比与选择标准
| 特性 | Early Numbering | Late Numbering |
|---|---|---|
| 生成时机 | 客户端提交前 | 服务器端处理时 |
| 用户体验 | 更流畅(立即显示ID) | 可能有短暂延迟 |
| 实现复杂度 | 需客户端逻辑 | 需服务器端逻辑 |
| 适用场景 | 简单自增ID | 复杂ID(如依赖其他数据) |
| 网络要求 | 适合高延迟环境 | 需要稳定连接 |
2-4. 实际应用示例
a.Early Numbering实现示例
abap
METHOD earlynumbering.
DATA: max_travel_id TYPE /dmo/travel_id.
" 获取当前最大ID
SELECT MAX( travel_id ) FROM /dmo/travel INTO @max_travel_id.
" 为新实体分配ID
LOOP AT entities INTO DATA(entity).
max_travel_id += 10.
mapped-travel = VALUE #( BASE mapped-travel
( %cid = entity-%cid travel_id = max_travel_id )
).
ENDLOOP.
ENDMETHOD.
b.Late Numbering实现示例
abap
METHOD latenumbering.
" 使用数据库序列获取新ID
LOOP AT entities INTO DATA(entity).
/dmo/cl_flight_amdp=>get_next_travel_id( IMPORTING ev_travel_id = DATA(travel_id) ).
mapped-travel = VALUE #( BASE mapped-travel
( %cid = entity-%cid travel_id = travel_id )
).
ENDLOOP.
ENDMETHOD.
2-5. 最佳实践建议
-
简单场景优先Early Numbering:当键值生成逻辑简单时,优先使用Early Numbering提升用户体验
-
复杂逻辑使用Late Numbering:当键值生成需要数据库访问或复杂计算时使用Late Numbering
-
混合使用:某些场景可以组合使用 - 先用Early Numbering提供临时ID,再用Late Numbering分配最终ID
-
考虑事务一致性:Late Numbering更适合需要严格事务一致性的场景
-
性能考量:Early Numbering减少服务器往返,但可能增加客户端复杂度
理解这两种编号策略的区别和适用场景,将帮助您设计出更高效、用户体验更好的Fiori Elements应用。
下面我们在系统上看一下如何做Numberling。
3,Early numbering - Travel ID
3-1,early numbering - Z04_DV_Travel_M (Behavior Definition)
a),加 association
- early numbering
- field ( readonly ) TravelId; =》因为既然已经是自带设定Key了,那么就不需要输入了嘛

b),Add earlynumbering method

它其实是在 Behavior Pool 里面生成了Method
METHODS earlynumbering_create FOR NUMBERING
IMPORTING entities FOR CREATE Z04_DV_Travel_M.
点一下 entities,然后按 F2

F2 是干啥的呢?
F2 - Show Code Element Information
看着像是你不知道某个元素是干啥的,点一下,然后按一下 F2,就能告诉你这个元素的详细

3-2,entities 参数详解
下面来看一下这些参数的含义。
entities type table for create z04_dv_travel_m
Components Mand. Create Mand. Save Readonly
%cid type abp_behv_cid
travelid type /dmo/travel_id
agencyid type /dmo/agency_id
customerid type /dmo/customer_id
begindate type /dmo/begin_date
enddate type /dmo/end_date
bookingfee type /dmo/booking_fee
totalprice type /dmo/total_price
currencycode type /dmo/currency_code
description type /dmo/description
overallstatus type /dmo/overall_status
createdby type abp_creation_user
createdat type abp_creation_tstmpl
lastchangedby type abp_locinst_lastchange_user
lastchangedat type abp_locinst_lastchange_tstmpl
%control [ control structure... ]
Component Groups
%data [ derived type... ]
%key [ derived type... ]
Primary Table Key
primary_key non-unique, standard, empty
Secondary Table Keys
cid non-unique, sorted, userdefined
%cid type abp_behv_cid
%key [ derived type... ]
entity (id) non-unique, sorted, userdefined
%key [ derived type... ]
在 RAP(ABAP RESTful Application Programming) 开发中,earlynumbering_create 方法是用于在创建实体时 提前分配业务键(如 ID) 的关键扩展点。当通过 F2 查看 entities 参数的说明时,显示的是该参数的详细结构信息。以下是逐部分解析:
a. 参数基础信息
abap
IMPORTING entities FOR CREATE Z04_DV_Travel_M.
-
作用:传入待创建的实体实例集合(
entities是一个内表,每个行项代表一个待创建的数据记录)。 -
类型:
FOR CREATE Z04_DV_Travel_M表示这是一个专为创建操作设计的动态结构,其字段与 CDS 实体Z04_DV_Travel_M的字段一致。
b. 参数结构详解
(1) 字段列表(Components)
| 字段名 | 类型 | Mand. Create | Mand. Save | Readonly | 说明 |
|---|---|---|---|---|---|
%cid | abp_behv_cid | - | - | - | 客户端的临时 ID(Client Identifier),用于在事务内跟踪新建的实体实例。 |
travelid | /dmo/travel_id | - | - | - | 业务主键(如旅行 ID),通常需要在 earlynumbering_create 中填充。 |
agencyid | /dmo/agency_id | ✔️ | ✔️ | - | 必填字段(如旅行社 ID),前端或逻辑需提供值。 |
customerid | /dmo/customer_id | ✔️ | ✔️ | - | 必填字段(如客户 ID)。 |
begindate | /dmo/begin_date | ✔️ | ✔️ | - | 必填字段(旅行开始日期)。 |
... | 其他业务字段(如费用、状态等)。 | ||||
createdby | abp_creation_user | - | - | ✔️ | 自动填充的创建用户,只读。 |
createdat | abp_creation_tstmpl | - | - | ✔️ | 自动填充的创建时间戳,只读。 |
%control | [控制结构] | - | - | - | 标记哪些字段被前端显式传值(用于部分更新场景)。 |
-
Mand. Create/Save:字段在创建或保存时是否必填(由 CDS 注解或行为定义控制)。
-
Readonly:字段是否仅由框架自动维护(如审计字段)。
(2) 组件组(Component Groups)
-
%data
包含所有业务字段的派生类型(Derived Type),对应 CDS 实体的完整数据结构。abap
-
DATA(lt_entities) = entities->%data. " 访问业务字段 -
%key
主键字段的派生类型(如travelid)。在earlynumbering_create中通常需要操作此字段:abap
-
LOOP AT entities ASSIGNING FIELD-SYMBOL(<fs_entity>). <fs_entity>-travelid = generate_travel_id(). " 生成业务键 ENDLOOP.
(3) 表键(Table Keys)
| 键名 | 类型 | 说明 |
|---|---|---|
| primary_key | 非唯一、标准、空 | 主表键(默认按 CDS 实体主键定义,如 travelid)。 |
| cid | 非唯一、排序、自定义 | 按 %cid 排序的辅助键,用于事务内跟踪临时实例。 |
| entity (id) | 非唯一、排序、自定义 | 按实体 ID 排序的辅助键(通常用于内部处理)。 |
c. 关键应用场景
(1) 自定义主键生成
在 earlynumbering_create 中,通常需要为 travelid 分配唯一值(如调用编号范围对象):
abap
METHOD earlynumbering_create.
LOOP AT entities ASSIGNING FIELD-SYMBOL(<fs_entity>)
WHERE travelid IS INITIAL. " 仅处理未提供ID的实例
<fs_entity>-travelid = cl_numberrange_runtime=>number_get(
EXPORTING
nr_range_nr = '01',
object = 'ZTRVL'
)-number.
ENDLOOP.
ENDMETHOD.
(2) 字段默认值逻辑
abap
METHOD earlynumbering_create.
LOOP AT entities ASSIGNING FIELD-SYMBOL(<fs_entity>).
IF <fs_entity>-overallstatus IS INITIAL.
<fs_entity>-overallstatus = 'N'; " 默认状态为New
ENDIF.
ENDLOOP.
ENDMETHOD.
(3) 控制字段访问
通过 %control 检查字段是否被显式传值:
abap
METHOD earlynumbering_create.
LOOP AT entities ASSIGNING FIELD-SYMBOL(<fs_entity>).
IF <fs_entity>-%control-agencyid = if_abap_behv=>mk-on.
" 前端显式提供了agencyid,可做校验
ENDIF.
ENDLOOP.
ENDMETHOD.
d. 注意事项
-
%cid的作用
用于在事务内关联操作(如后续的late numbering或save阶段),无需手动处理。 -
%control的用途
在部分更新(PATCH)场景中,标记哪些字段需被更新(未标记的字段会被忽略)。 -
与
late numbering的区别-
earlynumbering_create:在业务逻辑执行前分配键(如 ID)。 -
late numbering:在保存到数据库前最终处理键(如填充数据库自增字段)。
-
通过理解 entities 参数的结构,可以更精准地控制 RAP 实体的创建逻辑!
上面提到了一个概念 Drived type(派生类型)
3-3,RAP开发中,Fiori element里面,derived type是什么?
在 SAP Fiori Elements 开发中(基于 RAP 框架),Derived Type(派生类型) 是 ABAP CDS 或 RAP 模型中一种重要的数据类型复用机制,用于简化数据模型定义并增强一致性。以下是详细说明:
a. 核心概念
-
派生类型 是基于现有数据类型(如 CDS 实体字段、ABAP 字典类型等)创建的 逻辑扩展,继承原类型的属性(如数据类型、长度、语义),但允许追加额外的元数据(如注解、标签、默认值等)。
-
类似于面向对象中的“继承”,但仅作用于数据模型层。
b. 常见用途
在 Fiori Elements + RAP 开发中,派生类型通常用于:
-
标准化字段定义
例如,多个实体中重复使用的CustomerID字段,可通过派生类型统一语义和行为。 -
简化注解维护
将通用注解(如@UI、@Consumption)集中定义在派生类型中,避免重复。 -
增强可读性
通过有意义的类型名称(如derived type StatusCode)替代原始类型(如CHAR(4))。
c. 具体示例
(1) 在 CDS 中定义派生类型
abap
// 定义基础类型
@EndUserText.label: 'Status Code'
define type StatusCode : CHAR(4);
// 在实体中复用派生类型
define entity ZOrder {
key OrderID : UUID;
OrderStatus : StatusCode; // 使用派生类型
// ...其他字段
}
(2) 在 RAP BO 行为定义中
abap
// 行为定义中引用派生类型
define behavior for ZOrder {
field ( readonly ) OrderStatus as StatusCode; // 派生类型控制UI行为
// ...其他行为
}
d. Fiori Elements 中的效果
派生类型的 元数据(如标签、UI注解)会自动传递到 Fiori UI,例如:
-
表格列标题显示为
Status Code(来自派生类型的@EndUserText.label)。 -
若派生类型包含
@UI.hidden: true,则字段不会出现在界面上。
e. 与其他类型的区别
| 类型 | 派生类型 (Derived Type) | 自定义类型 (Custom Type) |
|---|---|---|
| 定义方式 | 基于现有类型扩展 | 完全独立定义 |
| 复用性 | 高(继承原类型属性) | 低(需完整定义) |
| 典型用途 | 标准化字段+注解 | 创建全新数据结构 |
f. 最佳实践
-
命名清晰:如
derived type CurrencyCode而非简单复用CHAR(3)。 -
集中管理:在公共 CDS 库中定义高频派生类型。
-
结合注解:通过派生类型统一控制UI行为(如字段必填、隐藏等)。
通过合理使用派生类型,可以显著提升 RAP 模型的 可维护性 和 Fiori Elements 的 一致性。
下面来看一些 derived type的实例
3-4,Derived Type(派生类型的实例)
在 SAP Fiori Elements 和 RAP(ABAP RESTful Application Programming) 开发中,Derived Type(派生类型) 可以显著提升代码复用性和可维护性。以下是更多实用的 Derived Type 示例,涵盖不同业务场景和优化技巧:
a. 基础数据类型标准化
(1) 通用业务键(Business Key)
abap
// 定义派生类型
@EndUserText.label: 'Business Partner ID'
define type BPID : UUID; // 或 CHAR(10) 等
// 在多个实体中复用
define entity ZCustomer {
key CustomerID : BPID; // 统一使用BPID类型
// ...
}
define entity ZSupplier {
key SupplierID : BPID; // 确保语义一致
// ...
}
作用:确保所有业务伙伴ID字段类型和语义一致,避免混用 CHAR(10) 和 CHAR(20) 等。
(2) 金额与货币
abap
// 定义金额和货币的派生类型
@Semantics.amount.currencyCode: 'CurrencyCode'
define type AmountValue : DEC(23,2);
@EndUserText.label: 'Currency Code'
define type CurrencyCode : CUKY; // CUKY = SAP货币类型
// 在订单实体中使用
define entity ZOrder {
NetAmount : AmountValue;
CurrencyCode : CurrencyCode;
// ...
}
作用:
-
自动关联金额与货币字段(通过
@Semantics注解)。 -
确保所有金额字段的小数位数一致(如财务要求 2 位小数)。
b. 状态与枚举值
(3) 标准化状态码
abap
// 派生类型 + 值帮助注解
@EndUserText.label: 'Order Status'
@Consumption.valueHelpDefinition: [{ entity: 'ZOrderStatus', element: 'Status' }]
define type OrderStatus : CHAR(2);
// 在行为定义中控制UI行为
define behavior for ZOrder {
field ( readonly ) Status as OrderStatus;
}
作用:
-
所有订单状态字段统一为
CHAR(2),并绑定相同的值帮助(Value Help)。 -
在 Fiori UI 中自动生成下拉列表。
(4) 布尔标志(Yes/No)
abap
// 定义语义化的布尔类型
@EndUserText.label: 'Active Flag'
define type ActiveFlag : abap.boolean; // ABAP内置布尔类型
// 在客户主数据中使用
define entity ZCustomer {
IsActive : ActiveFlag;
// ...
}
UI 效果:在 Fiori 表格中自动显示为 勾选框(Checkbox)。
c. 日期与时间
(5) 带语义的日期
abap
// 定义业务日期类型
@Semantics.systemDate.createdAt: true
define type CreatedDate : TIMESTAMP;
@Semantics.systemDate.lastChangedAt: true
define type ChangedDate : TIMESTAMP;
// 在实体中自动填充
define entity ZOrder {
CreatedAt : CreatedDate; // 自动记录创建时间
ChangedAt : ChangedDate; // 自动记录修改时间
}
作用:
-
自动捕获创建/修改时间(配合 RAP 框架的
@Semantics注解)。 -
避免手动定义
TIMESTAMP并重复写注解。
d. 复杂业务场景
(6) 地址信息组合
abap
// 定义地址组件派生类型
@EndUserText.label: 'Postal Code'
define type PostalCode : CHAR(10);
@EndUserText.label: 'Country Code'
define type CountryCode : CHAR(2);
// 在客户实体中复用
define entity ZCustomer {
PostalCode : PostalCode;
Country : CountryCode;
// ...
}
优化点:若地址规则变更(如邮编长度扩展),只需修改 PostalCode 的派生类型定义。
(7) 单位与数量
abap
// 定义单位派生类型(带值帮助)
@Consumption.valueHelpDefinition: [{ entity: 'ZUnits', element: 'Unit' }]
define type QuantityUnit : UNIT; // UNIT = SAP单位类型
@Semantics.quantity.unitOfMeasure: 'QuantityUnit'
define type QuantityValue : DEC(13,3);
// 在订单行项目中使用
define entity ZOrderItem {
Quantity : QuantityValue;
QuantityUnit : QuantityUnit;
}
Fiori 效果:
-
数量字段自动关联单位。
-
单位字段显示值帮助(如
KG,PC等)。
e. 派生类型的进阶用法
(8) 继承注解
abap
// 定义带UI注解的派生类型
@UI: {
lineItem: [ { position: 10, importance: #HIGH } ],
identification: [ { position: 10 } ]
}
define type ProductName : STRING(100);
// 在商品实体中直接复用
define entity ZProduct {
Name : ProductName; // 自动继承UI位置和重要性
// ...
}
优势:避免在每个实体中重复定义 @UI 注解。
(9) 跨服务复用
在 RAP 外部服务集成 中,通过派生类型保持与外部 API 的数据类型对齐:
abap
// 与外部系统一致的派生类型
define type API_ProductID : CHAR(18); // 匹配第三方系统ID格式
// 在本地实体中映射
define entity ZLocalProduct {
key ExternalID : API_ProductID;
// ...
}
f.最佳实践总结
-
语义化命名:如
EmailAddress而非CHAR(100)。 -
集中管理:在共享 DDL 源(如
ZCommonTypes)中定义高频派生类型。 -
结合注解:通过派生类型统一控制
@UI、@Semantics、值帮助等。 -
版本兼容:修改派生类型时评估对现有实体的影响。
通过合理使用派生类型,可以大幅减少重复代码,并确保 Fiori Elements UI 的一致性!
3-5,earlynumbering_create - 详解
这里就不展开了,想说一点,

在 RAP(ABAP RESTful Application Programming) 开发中,earlynumbering_create 方法是 行为定义(Behavior Definition) 中的一个关键扩展点,主要用于在创建实体时 提前分配业务键(如 ID) 或处理其他初始化逻辑。以下是按 F2 显示的代码结构的详细解析:
a. 方法签名说明
abap
METHODS earlynumbering_create FOR NUMBERING
IMPORTING
entities TYPE TABLE FOR CREATE z04_dv_travel_m " 待创建的实体数据
CHANGING
mapped TYPE RESPONSE FOR MAPPED EARLY z04_dv_travel_m " 成功映射的实体
failed TYPE RESPONSE FOR FAILED EARLY z04_dv_travel_m " 失败的实体
reported TYPE RESPONSE FOR REPORTED EARLY z04_dv_travel_m " 返回消息
(1) 输入参数 entities
-
类型:
TABLE FOR CREATE z04_dv_travel_m-
这是一个动态内表,结构与 CDS 实体
z04_dv_travel_m的字段一致,包含所有待创建的实例数据。 -
关键字段:
-
%cid:客户端临时 ID(Client Identifier),用于在事务内跟踪新建的实体。 -
业务键字段(如
travelid):通常需要在此方法中填充(若未由前端提供)。 -
其他业务字段(如
agencyid、description等)。
-
-
派生类型:实际类型是
z04_dv_travel_m%t_create(自动生成的派生类型)。
-
(2) 输出参数 mapped
-
类型:
RESPONSE FOR MAPPED EARLY z04_dv_travel_m-
用于返回 成功处理的实体映射关系(如生成的业务键与
%cid的对应关系)。 -
典型用法:
abap
-
-
-
mapped-z04_dv_travel_m = VALUE #( FOR <entity> IN entities WHERE ( travelid IS NOT INITIAL ) ( %cid = <entity>-%cid travelid = <entity>-travelid ) ). -
作用:确保后续操作(如
save阶段)能通过%cid找到正确的数据库键。
-
(3) 输出参数 failed
-
类型:
RESPONSE FOR FAILED EARLY z04_dv_travel_m-
用于标记 处理失败的实体(如业务键生成失败或校验不通过)。
-
示例:
abap
-
-
-
failed-z04_dv_travel_m = VALUE #( FOR <entity> IN entities WHERE ( agencyid IS INITIAL ) " 必填字段为空 ( %cid = <entity>-%cid %fail-cause = if_abap_behv=>cause-mandatory ) ). -
字段:
-
%cid:关联到失败的实体。 -
%fail-cause:失败原因(如if_abap_behv=>cause-mandatory表示必填字段缺失)。
-
-
(4) 输出参数 reported
-
类型:
RESPONSE FOR REPORTED EARLY z04_dv_travel_m-
用于返回 提示或错误消息(如校验失败的详细原因)。
-
示例:
abap
-
-
-
reported-z04_dv_travel_m = VALUE #( FOR <entity> IN entities WHERE ( agencyid IS INITIAL ) ( %cid = <entity>-%cid %msg = new_message( id = 'ZMSG' number = '001' severity = if_abap_behv=>msgerror v1 = 'Agency ID is mandatory' ) ) ). -
作用:在前端 Fiori UI 中显示自定义错误消息。
-
b. 典型代码实现示例
以下是一个完整的 earlynumbering_create 方法实现,包含 业务键生成 和 字段校验:
abap
METHOD earlynumbering_create.
DATA: lv_next_travelid TYPE /dmo/travel_id.
" 1. 为未提供 travelid 的实体生成业务键
LOOP AT entities ASSIGNING FIELD-SYMBOL(<fs_entity>)
WHERE travelid IS INITIAL.
" 调用编号范围对象生成唯一ID
lv_next_travelid = cl_numberrange_runtime=>number_get(
EXPORTING
nr_range_nr = '01',
object = 'ZTRVL'
)-number.
" 分配生成的ID
<fs_entity>-travelid = lv_next_travelid.
" 记录映射关系(cid -> travelid)
mapped-z04_dv_travel_m = VALUE #(
BASE mapped-z04_dv_travel_m
( %cid = <fs_entity>-%cid
travelid = lv_next_travelid
)
).
ENDLOOP.
" 2. 校验必填字段
LOOP AT entities ASSIGNING FIELD-SYMBOL(<fs_check>).
IF <fs_check>-agencyid IS INITIAL.
" 标记失败实体
failed-z04_dv_travel_m = VALUE #(
BASE failed-z04_dv_travel_m
( %cid = <fs_check>-%cid
%fail-cause = if_abap_behv=>cause-mandatory
)
).
" 返回错误消息
reported-z04_dv_travel_m = VALUE #(
BASE reported-z04_dv_travel_m
( %cid = <fs_check>-%cid
%msg = new_message(
id = 'ZMSG'
number = '001'
severity = if_abap_behv=>msgerror
v1 = 'Agency ID is mandatory'
)
)
).
ENDIF.
ENDLOOP.
ENDMETHOD.
c. 关键注意事项
-
%cid的作用-
由前端生成,用于在事务内唯一标识新建的实体实例。
-
必须在
mapped中正确关联%cid和生成的业务键,否则后续操作(如save)无法找到对应实例。
-
-
mapped的必要性-
如果未填充
mapped,框架无法将前端请求中的%cid映射到数据库键,导致后续逻辑错误。
-
-
错误处理优先级
-
若同时设置
failed和reported,前端会优先显示reported中的消息。
-
-
与
late numbering的区别-
earlynumbering_create:在业务逻辑执行前分配键(适合生成业务主键)。 -
late numbering:在保存到数据库前分配键(适合数据库自增字段)。
-
d. 常见业务场景
(1) 自动生成订单号
abap
<fs_entity>-orderid = cl_system_uuid=>create_uuid_c32( ). " 生成UUID
(2) 依赖外部系统的键分配
abap
CALL FUNCTION 'BAPI_PO_CREATE1'
EXPORTING
poheader = ls_po_header
IMPORTING
po_number = <fs_entity>-poid. " 从外部系统获取PO号
(3) 字段默认值
abap
IF <fs_entity>-status IS INITIAL.
<fs_entity>-status = 'NEW'. " 默认状态
ENDIF.
通过合理使用 earlynumbering_create,可以确保业务键的唯一性和一致性,同时实现灵活的校验逻辑。如果有更多具体场景需求,欢迎进一步探讨!
实战放在下一章里面,文章有点儿长了。
以上就是本篇的全部内容。
更多SAP顾问业务知识请点击下面目录链接或东京老树根的博客主页




1659

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



