上一章讲了Numbering 实战 Numbering- Travel ID,/DMO/TRV_M,debug,debug权限设定,异常处理等内容。
在继续写Booking ID/Booking Supplement ID 的Numbering 之前,来插一个知识点。
Read Entity 的各种模式:
- Read Entity - Short Form
- Read Entity - Long Form
- Read Entity - Dynamic Form
然后还简要聊了一下两个跟性能有关的Option
- IN LOCAL MODE
- PRIVILEGED
目录
1, Read Variant - Read Entity 概要
2, Read Variant - Read Entity, Short Form
2-2,Read Entity, Short Form - Travel
3, Read Variant - Read Entity, Long Form
4,Read Variant - Read Entities Operations, Dynamic Form
4-2,op = if_abap_behv=>op-r 出一个警告信息
5,Read Entity 选项:IN LOCAL MODE 与 PRIVILEGED
下面是详细内容。
1, Read Variant - Read Entity 概要
通过 Read Variant: 即读取数据。一共有3种读取数据的方式:
- Read Entity, Short Form
读取一条,比如我们的例子当中,读取Travel,Booking,Booking Supplement,任意1条
- Read Entity, Long Form
读取多条,比如 同时读取 Travel,以及关联的 Booking,或者再关联 Booking Supplement
- Read Entity, Dynamic Form
读取多条,动态读,功能跟 Long Form有点儿像,只是设定参数的时候,要动态设定
下面来看实例。
2, Read Variant - Read Entity, Short Form
2-1,创建Class
右键 Classes 文件夹 > NEW ABAP Class
输入 Name,Description,Interface
- Interface:IF_OO_ADT_CLASSRUN
选择TR,然后点Finish
这样Class 就Create好了,其中有个main 方法,代码就是从这里开始执行的。
2-2,Read Entity, Short Form - Travel
调用 Read Entity 的时候,需要输入Filter条件的参数,Result 变量接收结果,Failed 变量接受错误
如果有错误的话,简单打一个 out->write 来出力错误消息。
METHOD if_oo_adt_classrun~main.
* 3-1,Read Entity, Short Form - Travel
READ ENTITY Z04_DV_Travel_M
FROM VALUE #( ( %key-TravelId = '00025442' ) )
RESULT DATA(lt_result_travel)
FAILED DATA(lt_failed_travel).
IF lt_failed_travel IS NOT INITIAL.
out->write( 'Read failed' ).
ELSE.
out->write( lt_result_travel ).
ENDIF.
ENDMETHOD.
按下 Ctrl + F3 激活,然后按下 F9 执行
显示执行结果:
TRAVELID AGENCYID CUSTOMERID BEGINDATE ENDDATE BOOKINGFEE TOTALPRICE CURRENCYCODE DESCRIPTION OVERALLSTATUS CREATEDBY CREATEDAT LASTCHANGEDBY LASTCHANGEDAT
00025442 000000 000000 0000-00-00 0000-00-00 0.0 0.0
这个结果是不是有点儿奇怪,只得到了 Travel ID,其他的都是初始值。
那么要怎么查询到其他字段的值呢?
需要指定字段。
a),通过 control 进行指定字段
点 %control,然后按下 F2,能看到control 里有些什么字段
做法就是将 if_abap_behv=>mk 设为 ON (01)
因为默认的话,control 里面,各个字段就是 off 的,你想要Read出来那个字段你得手动打开
%control = VALUE #( AgencyId = if_abap_behv=>mk-on )
把 CustomerId,BeginDate 也给加上
FROM VALUE #( ( %key-TravelId = '00025442'
%control = VALUE #( AgencyId = if_abap_behv=>mk-on
CustomerId = if_abap_behv=>mk-on
BeginDate = if_abap_behv=>mk-on
)
) )
按下 Ctrl + F3 激活,然后按下 F9 执行
这样指定的几个字段就能把数据抽出来了:
TRAVELID AGENCYID CUSTOMERID BEGINDATE ENDDATE BOOKINGFEE TOTALPRICE CURRENCYCODE DESCRIPTION OVERALLSTATUS CREATEDBY CREATEDAT LASTCHANGEDBY LASTCHANGEDAT
00025442 070008 000008 2025-07-28 0000-00-00 0.0 0.0 0.0 0.0
b),通过 Fields 进行指定字段
除了上面通过 control 进行指定之外,还可以通过 Fields 进行指定。
FIELDS ( AgencyId BookingFee EndDate BeginDate )
这种写法是不是简单些,好像跟咱们的印象中更接近些。
按下 Ctrl + F3 激活,然后按下 F9 执行
这样指定的几个字段就能把数据抽出来了:
TRAVELID AGENCYID CUSTOMERID BEGINDATE ENDDATE BOOKINGFEE TOTALPRICE CURRENCYCODE DESCRIPTION OVERALLSTATUS CREATEDBY CREATEDAT LASTCHANGEDBY LASTCHANGEDAT
00025442 070008 000000 2025-07-28 2025-07-30 4.0 0.0 0.0 0.0
这种方法还有个好处,就是当你想抽出所有字段的时候,可以用All
按下 Ctrl + F3 激活,然后按下 F9 执行
这就接近SQL 语句了哈
TRAVELID AGENCYID CUSTOMERID BEGINDATE ENDDATE BOOKINGFEE TOTALPRICE CURRENCYCODE DESCRIPTION OVERALLSTATUS CREATEDBY CREATEDAT LASTCHANGEDBY LASTCHANGEDAT
00025442 070008 000008 2025-07-28 2025-07-30 4.0 124.0 USD Des06 O 0.0 20250728094401.516872
c),查询多条数据
指定多个条件
WITH VALUE #( ( %key-TravelId = '00025442' )
( %key-TravelId = '00025441' )
)
按下 Ctrl + F3 激活,然后按下 F9 执行
d),查询association 表的数据
做法就是加个 by \_Booking
按下 Ctrl + F3 激活,然后按下 F9 执行
这样查出来的就是 Booking 表的数据:
TRAVELID BOOKINGID BOOKINGDATE CUSTOMERID CARRIERID CONNECTIONID FLIGHTDATE FLIGHTPRICE CURRENCYCODE BOOKINGSTATUS LASTCHANGEDAT
00025326 0001 2025-12-08 000233 JL 0407 2025-12-26 7972.0 JPY N 20250627002747.0
00025326 0002 2025-12-08 000397 JL 0407 2025-12-26 7972.0 JPY N 20250627002747.0
00025337 0010 2025-07-09 000004 AF 0000 0000-00-00 0.0 0.0
00025337 0020 2025-07-12 000003 AA 2678 0000-00-00 0.0 0.0
00025337 0030 2025-07-29 000006 AF 0000 0000-00-00 0.0 0.0
3, Read Variant - Read Entity, Long Form
Long Form的代码如下:
- READ ENTITIES OF Z04_DV_Travel_M =》指明 root Entity
- ENTITY Z04_DV_Travel_M,ENTITY Z04_DV_Booking_M =》这是指明具体要取哪个表的数据
- Key =》指明具体要取哪条数据,这里必须指明所有key,单个key取不出来
那你想取所有数据怎么办?用 3-2)的 d,查 association 表的所有关联数据,或者
你还可以在这里给多个条件也可以
READ ENTITIES OF Z04_DV_Travel_M
ENTITY Z04_DV_Travel_M
ALL FIELDS
WITH VALUE #( ( %key-TravelId = '00025337' )
( %key-TravelId = '00025326' )
)
RESULT DATA(lt_result_travel)
ENTITY Z04_DV_Booking_M
ALL FIELDS
WITH VALUE #( ( %key-TravelId = '00025337' %key-BookingId = '0020' )
( %key-TravelId = '00025326' %key-BookingId = '0001' )
)
RESULT DATA(lt_result_booking)
FAILED DATA(lt_failed).
IF lt_failed IS NOT INITIAL.
out->write( 'Read failed' ).
ELSE.
out->write( lt_result_travel ).
out->write( lt_result_booking ).
ENDIF.
按下 Ctrl + F3 激活,然后按下 F9 执行
这样查出来的就是 Travel 表 和 Booking 表的数据:
TRAVELID AGENCYID CUSTOMERID BEGINDATE ENDDATE BOOKINGFEE TOTALPRICE CURRENCYCODE DESCRIPTION OVERALLSTATUS CREATEDBY CREATEDAT LASTCHANGEDBY LASTCHANGEDAT
00025337 070001 000005 2025-07-01 2025-07-09 500.0 500.0 EUR O CB9980022391 20250710154105.016298 CB9980008383 20250714151244.999928
00025326 070010 000033 2025-12-26 2025-12-26 20.0 15976.0 JPY Business Trip for Adam, Theresia O Vrsic 20250624153619.0 Domenech 20250627002747.0
TRAVELID BOOKINGID BOOKINGDATE CUSTOMERID CARRIERID CONNECTIONID FLIGHTDATE FLIGHTPRICE CURRENCYCODE BOOKINGSTATUS LASTCHANGEDAT
00025337 0020 2025-07-12 000003 AA 2678 0000-00-00 0.0 0.0
00025326 0001 2025-12-08 000233 JL 0407 2025-12-26 7972.0 JPY N 20250627002747.0
下面来看看Dynamic 的例子。
4,Read Variant - Read Entities Operations, Dynamic Form
4-1,取 Travel_M 的数据
DATA: it_optab TYPE abp_behv_retrievals_tab, =》定义Dynamic内表
it_travel TYPE TABLE FOR READ IMPORT Z04_DV_Travel_M, =》抽出对象
it_travel_result TYPE TABLE FOR READ RESULT Z04_DV_Travel_M. =》抽出结果
op = if_abap_behv=>op-r =》指明针对该Dynamic Form,你打算做什么操作,比如这里是Read
READ ENTITIES
OPERATIONS it_optab
FAILED DATA(lt_failed_dy). =》指定完了所有参数,就可以调用Read Entites来取结果了
DATA: it_optab TYPE abp_behv_retrievals_tab,
it_travel TYPE TABLE FOR READ IMPORT Z04_DV_Travel_M,
it_travel_result TYPE TABLE FOR READ RESULT Z04_DV_Travel_M.
it_travel = VALUE #( ( %key-TravelId = '00025337'
%control = VALUE #( AgencyId = if_abap_behv=>mk-on
CustomerId = if_abap_behv=>mk-on
BeginDate = if_abap_behv=>mk-on
)
) ).
it_optab = VALUE #( ( op = if_abap_behv=>op-r
entity_name = 'Z04_DV_TRAVEL_M'
instances = REF #( it_travel )
results = REF #( it_travel_result )
) ).
READ ENTITIES
OPERATIONS it_optab
FAILED DATA(lt_failed_dy).
IF lt_failed_dy IS NOT INITIAL.
out->write( 'Read failed' ).
ELSE.
out->write( it_travel_result ).
ENDIF.
按下 Ctrl + F3 激活,然后按下 F9 执行
这样就查出来 Travel 表的数据了:
TRAVELID AGENCYID CUSTOMERID BEGINDATE ENDDATE BOOKINGFEE TOTALPRICE CURRENCYCODE DESCRIPTION OVERALLSTATUS CREATEDBY CREATEDAT LASTCHANGEDBY LASTCHANGEDAT
00025337 070001 000005 2025-07-01 0000-00-00 0.0 0.0 0.0 0.0
op = if_abap_behv=>op-r 这一行出了个警告信息:
Multiple markers at this line:
- "R:{READ:'R',READ_BA:'N',EVALUATE:'E'}" is not an admissible value for type "C(1)". Admissible: R.
- The compatibility of type "ABP_BEHV_OP_READ" with "IF_ABAP_BEHV=>OP-R" is not guaranteed. The type might be extended in the future.
- (
4-2,op = if_abap_behv=>op-r 出一个警告信息
在代码中,op = if_abap_behv=>op-r 这一行出现了三个相关警告:
-
类型不匹配警告:
"R:{READ:'R',READ_BA:'N',EVALUATE:'E'}"不是C(1)类型的有效值 -
兼容性警告:
ABP_BEHV_OP_READ与IF_ABAP_BEHV=>OP-R的兼容性不能保证 -
语法警告:括号不匹配(可能是编辑器解析问题)
a,问题原因
这些警告源于 ABAP RAP 框架中操作类型的定义方式。if_abap_behv=>op-r 实际上返回的是一个复杂结构,而 abp_behv_retrievals_tab 中的 op 字段期望的是一个简单的字符 'R'。
b,解决方案
有两种方法可以解决这个问题:
b-1:直接使用字符值 'R'
abap
it_optab = VALUE #( ( op = 'R' "直接使用字符'R'而不是if_abap_behv=>op-r
entity_name = 'Z04_DV_TRAVEL_M'
instances = REF #( it_travel )
results = REF #( it_travel_result )
) ).
b-2:使用正确的常量(推荐)
abap
it_optab = VALUE #( ( op = if_abap_behv=>operation-read "使用正确的常量
entity_name = 'Z04_DV_TRAVEL_M'
instances = REF #( it_travel )
results = REF #( it_travel_result )
) ).
这样确实就没有错误了:😓
我感觉 RAP 对这个 Dynamic Form的支持好像不太友好呢哈。
4-3,取 Booking_M 的数据
比较重要的是下面这行代码:
op = if_abap_behv=>op-r-read_ba =》 ba 是 by association 的意思,取Travel 的关联表 Booking
上面 5-2 说的警告,其实改为 op = if_abap_behv=>op-r-read 就可以了😓惭愧惭愧
* 3-4,Read Entity, Dynamic - Travel - Fields
DATA: it_optab TYPE abp_behv_retrievals_tab,
it_travel TYPE TABLE FOR READ IMPORT Z04_DV_Travel_M,
it_travel_result TYPE TABLE FOR READ RESULT Z04_DV_Travel_M,
it_booking TYPE TABLE FOR READ IMPORT Z04_DV_Travel_M\_Booking,
it_booking_result TYPE TABLE FOR READ RESULT Z04_DV_Travel_M\_Booking.
it_travel = VALUE #( ( %key-TravelId = '00025337'
%control = VALUE #( AgencyId = if_abap_behv=>mk-on
CustomerId = if_abap_behv=>mk-on
BeginDate = if_abap_behv=>mk-on
)
) ).
it_booking = VALUE #( ( %key-TravelId = '00025337'
%control = VALUE #( BookingDate = if_abap_behv=>mk-on
BookingStatus = if_abap_behv=>mk-on
BookingId = if_abap_behv=>mk-on
)
) ).
it_optab = VALUE #( ( op = if_abap_behv=>op-r-read
entity_name = 'Z04_DV_TRAVEL_M'
instances = REF #( it_travel )
results = REF #( it_travel_result ) )
( op = if_abap_behv=>op-r-read_ba
entity_name = 'Z04_DV_TRAVEL_M'
sub_name = '_BOOKING'
instances = REF #( it_booking )
results = REF #( it_booking_result ) )
).
READ ENTITIES
OPERATIONS it_optab
FAILED DATA(lt_failed_dy).
IF lt_failed_dy IS NOT INITIAL.
out->write( 'Read failed' ).
ELSE.
out->write( it_travel_result ).
out->write( it_booking_result ).
ENDIF.
按下 Ctrl + F3 激活,然后按下 F9 执行
看来这个就是可以把Travel ID 关联的所有Booking 都能取出来:
TRAVELID AGENCYID CUSTOMERID BEGINDATE ENDDATE BOOKINGFEE TOTALPRICE CURRENCYCODE DESCRIPTION OVERALLSTATUS CREATEDBY CREATEDAT LASTCHANGEDBY LASTCHANGEDAT
00025337 070001 000005 2025-07-01 0000-00-00 0.0 0.0 0.0 0.0
TRAVELID BOOKINGID BOOKINGDATE CUSTOMERID CARRIERID CONNECTIONID FLIGHTDATE FLIGHTPRICE CURRENCYCODE BOOKINGSTATUS LASTCHANGEDAT
00025337 0010 2025-07-09 000000 0000 0000-00-00 0.0 0.0
00025337 0020 2025-07-12 000000 0000 0000-00-00 0.0 0.0
00025337 0030 2025-07-29 000000 0000 0000-00-00 0.0 0.0
5,Read Entity 选项:IN LOCAL MODE 与 PRIVILEGED
在 ABAP RESTful Application Programming (RAP) 框架中,READ ENTITIES 操作提供了两个重要的读取选项:IN LOCAL MODE 和 PRIVILEGED。这两个选项在数据访问控制和性能优化方面有不同用途。
5-1. IN LOCAL MODE
a,用途
IN LOCAL MODE 选项用于在当前事务上下文(即本地模式)中执行读取操作,绕过授权检查和业务对象处理逻辑(如determinations和validations)。
b,特点
-
性能更高(跳过业务逻辑处理)
-
不触发后续的determinations/validations
-
忽略授权检查
-
仅适用于当前事务内的数据(不考虑未提交的更改)
c,使用场景
-
需要高性能读取时
-
在determination/validation逻辑内部需要读取数据时
-
不需要授权检查的内部处理
d,示例代码
abap
READ ENTITIES OF ZRAP_Travel_M
IN LOCAL MODE
ENTITY Travel
ALL FIELDS WITH CORRESPONDING #( keys )
RESULT DATA(lt_travel_data).
5-2. PRIVILEGED
a,用途
PRIVILEGED 选项用于绕过授权检查,但仍会执行业务对象处理逻辑。
b,特点
-
执行完整的业务逻辑(determinations/validations)
-
跳过授权检查
-
性能比IN LOCAL MODE略低
-
可以访问跨事务的数据
c,使用场景
-
需要完整业务逻辑但不需要授权检查的场景
-
后台作业或管理员功能
-
需要读取跨事务数据时
d,示例代码
abap
READ ENTITIES OF ZRAP_Travel_M
PRIVILEGED
ENTITY Travel
FIELDS ( TravelID Description StartDate EndDate )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_travel_data).
5-3. 对比总结
| 特性 | IN LOCAL MODE | PRIVILEGED |
|---|---|---|
| 授权检查 | 跳过 | 跳过 |
| 业务逻辑 | 跳过 | 执行 |
| 性能 | 最高 | 中等 |
| 数据可见性 | 仅当前事务 | 跨事务 |
| 典型用途 | 内部处理/高性能读取 | 管理功能/特权访问 |
5.4. 最佳实践建议
-
生产代码中应谨慎使用这两个选项,因为它们会绕过安全控制
-
优先使用标准读取(不加选项),确保数据一致性和安全性
-
在以下情况考虑使用特殊选项:
-
确定性能是关键因素时(用IN LOCAL MODE)
-
实现需要绕过授权的管理功能时(用PRIVILEGED)
-
-
在behavior definition中明确记录使用了这些选项的原因
5.5 完整示例场景
abap
METHOD read_travel_data.
DATA: lt_keys TYPE TABLE FOR READ IMPORT ZRAP_Travel_M\\Travel.
" 标准读取(带授权检查和业务逻辑)
READ ENTITIES OF ZRAP_Travel_M
ENTITY Travel
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(lt_standard_data).
" 高性能读取(内部处理用)
READ ENTITIES OF ZRAP_Travel_M
IN LOCAL MODE
ENTITY Travel
FIELDS ( TravelID, Status )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_fast_data).
" 特权读取(管理员功能)
READ ENTITIES OF ZRAP_Travel_M
PRIVILEGED
ENTITY Travel
FIELDS ( TravelID, CustomerID, TotalPrice )
WITH VALUE #( ( %key-TravelID = '12345' ) )
RESULT DATA(lt_admin_data).
ENDMETHOD.
这两个选项为RAP开发提供了灵活的读取控制,但应谨慎使用以确保系统安全性和数据一致性。
以上就是本篇的全部内容。
更多SAP顾问业务知识请点击下面目录链接或东京老树根的博客主页


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



