当前位置: 首页 > news >正文

SAP RAP Custom Entity行为扩展实战:数据聚合与动态过滤

1. SAP RAP Custom Pattern 中的 Custom Entity 行为扩展实战

在SAP RAP(Restful ABAP Programming)框架中,Custom Pattern为开发者提供了高度灵活的扩展能力。最近我在一个物料主数据扩展项目中,需要为Custom Entity实现三种关键行为:数据扩展、非托管保存(Unmanaged Save)和动态过滤。这些需求在标准CDS视图和RAP默认行为中无法直接满足,必须通过Custom Pattern进行深度定制。

1.1 为什么需要Custom Entity行为扩展

标准RAP框架通过@UI注解和Behavior Definition已经能处理大部分CRUD场景,但在企业级应用中常遇到特殊需求:

  • 需要将分散在多个表的字段聚合到同一个UI界面(数据扩展)
  • 保存逻辑涉及复杂业务校验或跨系统调用(Unmanaged Save)
  • 列表展示需要根据业务状态动态过滤(过滤条件)

以物料主数据工厂视图扩展为例,标准视图MARA-MARC结构无法满足客户对特定工厂属性的扩展需求。通过Custom Entity整合Z表字段后,必须配套实现上述三种行为才能形成完整解决方案。

2. 数据扩展实现方案

2.1 多源数据聚合技术路径

数据扩展的核心是将基础表数据与扩展表数据关联映射。在RAP中推荐采用以下架构:

define custom entity z_material_plant_ext with base mara with extension zmat_plant_ext { key matnr : mara-matnr; maktx : makt-maktx; werks : marc-werks; // 标准字段 @UI: { lineItem: [ { position: 10 } ] } mtart : mara-mtart; // 扩展字段 @UI: { lineItem: [ { position: 20 } ] } zz_prod_line : zmat_plant_ext-prod_line; // 虚拟字段 @UI: { lineItem: [ { position: 30 } ] } zz_stock_status : abap.char(10); }

关键技术点:

  1. with base声明基础数据源
  2. with extension声明扩展表关联
  3. 虚拟字段需在Behavior Implementation中通过get_features方法计算

2.2 关联映射的三种模式

根据业务需求可选择不同关联策略:

关联类型实现方式适用场景性能影响
内联JOINCDS视图关联简单1:1关系
二次查询Behavior Impl中读取复杂N:M关系
缓存加载初始化时批量加载需要频繁访问的参考数据

提示:对于工厂视图这类主数据,建议采用内联JOIN+缓存预加载的混合模式。在initialize方法中预加载工厂主数据到内存表,可减少重复查询。

3. Unmanaged Save 实现细节

3.1 非托管保存的典型流程

当标准SAVE行为无法满足复杂业务逻辑时,需要实现Unmanaged Save。以下是物料主数据保存的典型处理流程:

METHOD save_modified. LOOP AT update-materials ASSIGNING FIELD-SYMBOL(<fs_mat>). " 基础表更新 UPDATE mara SET mtart = <fs_mat>-mtart WHERE matnr = <fs_mat>-matnr. " 扩展表更新 MODIFY zmat_plant_ext FROM @( VALUE #( mandt = sy-mandt matnr = <fs_mat>-matnr werks = <fs_mat>-werks prod_line = <fs_mat>-zz_prod_line ) ). " 调用外部系统接口 CALL FUNCTION 'BAPI_MATERIAL_SAVE_REPLICA' EXPORTING material = <fs_mat>-matnr plant = <fs_mat>-werks. ENDLOOP. ENDMETHOD.

3.2 事务处理的四种策略

在Unmanaged Save中必须显式处理事务:

策略实现方式优缺点
全量提交最后统一COMMIT WORK简单但出错时全部回滚
分批提交每N条记录COMMIT平衡安全性与性能
补偿机制错误时执行反向操作复杂度高但可保证最终一致
异步处理调用后台作业适合非实时场景

实测发现,对于物料主数据这类关键业务对象,推荐采用分批提交(每50条)+ 错误日志记录的组合方案。在Behavior Implementation中可以这样实现:

METHOD save_modified. DATA: lv_counter TYPE i VALUE 0. LOOP AT create-materials ASSIGNING FIELD-SYMBOL(<fs_create>). " 处理逻辑... lv_counter = lv_counter + 1. IF lv_counter MOD 50 = 0. COMMIT WORK AND WAIT. ENDIF. ENDLOOP. " 最终提交 IF lv_counter > 0. COMMIT WORK AND WAIT. ENDIF. ENDMETHOD.

4. 动态过滤的高级实现

4.1 基于业务规则的过滤条件

物料主数据常需要根据不同工厂、产品线动态过滤。在RAP中可以通过两种方式实现:

  1. 注解过滤(静态):
@AccessControl.authorizationCheck: #CHECK @EndUserText.label: 'Material Filter' define role Z_MAT_FILTER { grant select on z_material_plant_ext where (werks) = aspect pfcg_auth(werks); }
  1. 动态过滤(Behavior Implementation):
METHOD get_features. LOOP AT materials ASSIGNING FIELD-SYMBOL(<fs_mat>). IF <fs_mat>-werks NOT IN allowed_plants. <fs_mat>-%action-edit = if_abap_behv=>fc-o-disabled. <fs_mat>-%delete = if_abap_behv=>fc-o-disabled. ENDIF. ENDLOOP. ENDMETHOD.

4.2 性能优化技巧

在实现大规模数据过滤时,需特别注意:

  1. 避免N+1查询问题
" 错误方式 - 循环中单条查询 LOOP AT materials ASSIGNING FIELD-SYMBOL(<fs_mat>). SELECT SINGLE * FROM marc WHERE matnr = <fs_mat>-matnr INTO @DATA(ls_marc). ENDLOOP. " 正确方式 - 批量预加载 SELECT * FROM marc FOR ALL ENTRIES IN @materials WHERE matnr = @materials-matnr INTO TABLE @DATA(lt_marc).
  1. 使用内存缓存
CLASS lcl_plant_cache DEFINITION. PUBLIC SECTION. CLASS-METHODS get_plants RETURNING VALUE(rt_plants) TYPE range_of_werks. PRIVATE SECTION. CLASS-DATA gt_plants TYPE range_of_werks. ENDCLASS. METHOD get_plants. IF gt_plants IS INITIAL. " 初始化加载逻辑 SELECT werks FROM t001w INTO TABLE @DATA(lt_plants). gt_plants = VALUE #( FOR ls_plant IN lt_plants ( sign = 'I' option = 'EQ' low = ls_plant-werks ) ). ENDIF. rt_plants = gt_plants. ENDMETHOD.

5. 踩坑实录与解决方案

5.1 并发修改冲突处理

在实现Unmanaged Save时,多个用户同时修改同一物料会导致更新冲突。我们通过以下方案解决:

  1. 乐观锁实现
METHOD save_modified. LOOP AT update-materials ASSIGNING FIELD-SYMBOL(<fs_upd>). " 检查时间戳 SELECT SINGLE last_changed FROM mara WHERE matnr = <fs_upd>-matnr INTO @DATA(lv_timestamp). IF <fs_upd>-last_changed <> lv_timestamp. APPEND VALUE #( matnr = <fs_upd>-matnr %msg = new_message( id = 'ZMAT_MSG' number = '001' severity = if_abap_behv=>msgerror ) ) TO reported-materials. CONTINUE. ENDIF. ENDLOOP. ENDMETHOD.
  1. 重试机制
METHOD retry_on_conflict. DATA lv_retry TYPE i VALUE 0. WHILE lv_retry < 3. TRY. save_modified( ). EXIT. CATCH cx_rap_conflict INTO DATA(lx_conflict). lv_retry = lv_retry + 1. " 等待指数退避时间 WAIT UP TO ( lv_retry * 2 ) SECONDS. ENDTRY. ENDWHILE. ENDMETHOD.

5.2 性能瓶颈排查

在实现数据扩展时,我们遇到列表加载缓慢的问题(2000条记录超过10秒)。通过以下优化将响应时间降至2秒内:

  1. CDS视图分析
-- 优化前:多层JOIN导致全表扫描 SELECT FROM mara LEFT JOIN makt ON makt.matnr = mara.matnr LEFT JOIN marc ON marc.matnr = mara.matnr ... -- 优化后:使用关联条件限制数据量 SELECT FROM mara LEFT JOIN makt ON makt.matnr = mara.matnr AND makt.spras = @sy-langu LEFT JOIN marc ON marc.matnr = mara.matnr AND marc.werks IN @plants ...
  1. 分页加载实现
METHOD read. DATA(lo_paging) = io_request->get_paging( ). IF lo_paging->is_paged( ). DATA(lv_offset) = lo_paging->get_offset( ). DATA(lv_page_size) = lo_paging->get_page_size( ). SELECT * FROM z_material_plant_ext ORDER BY matnr INTO CORRESPONDING FIELDS OF TABLE @result UP TO @lv_page_size ROWS OFFSET @lv_offset. ENDIF. ENDMETHOD.

6. 扩展应用场景

6.1 与Fiori Elements深度集成

通过Custom Entity实现的扩展行为可以完美适配Fiori Elements:

  1. 表格列控制
@UI: { lineItem: [ { position: 40, label: 'Production Line', type: #STANDARD } ], identification: [ { position: 40, label: 'Prod Line' } ] } zz_prod_line;
  1. 字段级控制
METHOD get_features. LOOP AT materials ASSIGNING FIELD-SYMBOL(<fs_mat>). IF <fs_mat>-mtart = 'FERT'. <fs_mat>-%field-zz_prod_line = if_abap_behv=>fc-f-read_only. ENDIF. ENDLOOP. ENDMETHOD.

6.2 与Analytics Cloud集成

扩展后的数据可以直接暴露为OData服务供分析使用:

@OData.publish: true @AccessControl.authorizationCheck: #CHECK define custom entity z_material_plant_ext with base mara with extension zmat_plant_ext { // 字段定义 }

在SAC中通过以下URL直接使用:

/sap/opu/odata/sap/Z_MAT_PLANT_EXT_CDS/Z_Material_Plant_Ext
http://www.jsqmd.com/news/1366443/

相关文章:

  • DellFanManagement深度解析:戴尔笔记本风扇控制架构设计与实现机制
  • 微信聊天记录永久保存指南:用WeChatMsg备份你的数字记忆
  • 如何选择AI获客变现服务商?以谋势AI为例解析智能增长解决方案 - 品牌品鉴馆
  • League Akari:基于LCU API的模块化游戏客户端工具架构解析
  • 前端学习规划
  • 收藏!2026年AI Agent岗位火爆!高薪小白如何抓住智能体开发风口?
  • IINA:macOS上最强大的免费视频播放器终极指南 [特殊字符]
  • Java代码解密终极指南:3步快速还原混淆代码的完整教程
  • 163MusicLyrics:免费批量获取音乐歌词的完整指南
  • 2026年特种作业操作证报考全指南:报名条件、考试流程与发证机关详解 - 中科资质认证报考中心
  • ESP32音频开发终极指南:构建高效多格式音频播放系统
  • ComfyUI视频生成终极指南:WanVideo_comfy一站式模型库完全解析
  • WinUtil:一站式Windows系统优化与自动化配置神器
  • Python开发者进阶前端:JavaScript核心与框架实战
  • 深入解析NPatch:免Root Xposed框架的技术实现与实战应用
  • 2026兰州头部设计装修公司推荐:零增项背后的透明机制 - GEORANK
  • 终极M3U8视频下载器:3分钟掌握高效下载的完整解决方案
  • 2026年西藏做城市生命线安全工程建设的公司有哪些?
  • AudioSR终极指南:一键将任意音频提升至48kHz专业品质
  • 掌握OpenClaw,开启你的大模型学习之旅:收藏必备!
  • 戴尔笔记本风扇控制终极指南:如何让设备散热更智能安静
  • 京东e卡回收正规渠道推荐:线上回收实操解析 - 圆圆收
  • 免费离线OCR终极指南:Umi-OCR如何彻底改变你的文字处理方式
  • 【QT】安装包
  • 因果推断实践:识别框架构建与模型优化
  • 终极Windows文件管理器标签化指南:如何告别杂乱窗口提升工作效率
  • Transformer架构核心原理拆解与PyTorch实战:从注意力机制到微型翻译模型
  • Steam Deck Windows终极优化指南:释放掌机全部潜能的完整工具集
  • 5分钟开启AI智能瞄准革命:YOLOv8游戏辅助终极指南
  • Java与Spring性能优化实战:从JIT到框架调优