SAP学习笔记 - 开发52 - RAP开发 Managed App Read Entity - Short Form,Long Form,Dynamic Form

 上一章讲了Numbering 实战 Numbering- Travel ID,/DMO/TRV_M,debug,debug权限设定,异常处理等内容。

SAP学习笔记 - 开发51 - RAP开发 Managed App Numbering 实战 Numbering- Travel ID,/DMO/TRV_M,debug,debug权限设定,异常处理-CSDN博客

在继续写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-1,创建Class

2-2,Read Entity, Short Form - Travel

a),通过 control 进行指定字段

b),通过 Fields 进行指定字段

c),查询多条数据

d),查询association 表的数据

3, Read Variant - Read Entity, Long Form

4,Read Variant - Read Entities Operations, Dynamic Form

4-1,取 Travel_M 的数据

4-2,op = if_abap_behv=>op-r 出一个警告信息

a,问题原因

b,解决方案

b-1:直接使用字符值 'R'

b-2:使用正确的常量(推荐)

4-3,取 Booking_M 的数据

5,Read Entity 选项:IN LOCAL MODE 与 PRIVILEGED

5-1. IN LOCAL MODE

a,用途

b,特点

c,使用场景

d,示例代码

5-2. PRIVILEGED

a,用途

b,特点

c,使用场景

d,示例代码

5-3. 对比总结

5.4. 最佳实践建议

5.5 完整示例场景


下面是详细内容。

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 这一行出现了三个相关警告:

  1. 类型不匹配警告"R:{READ:'R',READ_BA:'N',EVALUATE:'E'}" 不是 C(1) 类型的有效值

  2. 兼容性警告ABP_BEHV_OP_READIF_ABAP_BEHV=>OP-R 的兼容性不能保证

  3. 语法警告:括号不匹配(可能是编辑器解析问题)

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 MODEPRIVILEGED。这两个选项在数据访问控制和性能优化方面有不同用途。

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 MODEPRIVILEGED
授权检查跳过跳过
业务逻辑跳过执行
性能最高中等
数据可见性仅当前事务跨事务
典型用途内部处理/高性能读取管理功能/特权访问

5.4. 最佳实践建议

  1. 生产代码中应谨慎使用这两个选项,因为它们会绕过安全控制

  2. 优先使用标准读取(不加选项),确保数据一致性和安全性

  3. 在以下情况考虑使用特殊选项:

    • 确定性能是关键因素时(用IN LOCAL MODE)

    • 实现需要绕过授权的管理功能时(用PRIVILEGED)

  4. 在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顾问业务知识请点击下面目录链接或东京老树根的博客主页

https://blog.csdn.net/shi_ly/category_12216766.html

东京老树根-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值