基于类框架的ABAP内表动态拆分为批次的技术实现问题
在基于类的ABAP框架中,父类的process_in_batch方法需要将子类重定义prepare_data方法返回的任意类型数据拆分为指定批次大小,再调用后台函数逐个处理批次数据。父类execute方法中通过process_in_batch( prepare_data( ) )调用这两个方法,其中prepare_data由子类重定义以获取业务数据。
初始代码与编译错误
作者最初编写的代码如下:
FIELD-SYMBOLS: <lt_data> TYPE ANY TABLE. "Dereference the keys data supplied ASSIGN ir_data->* TO <lt_data>. IF sy-subrc EQ 0. FIELD-SYMBOLS: <lt_package_data> TYPE ANY TABLE. DATA: lr_data_package_ref TYPE REF TO data. CREATE DATA lr_data_package_ref LIKE <lt_data>. ASSIGN lr_data_package_ref->* TO <lt_package_data>. "Process dataset in batches of size requested LOOP AT <lt_data> INTO DATA(ls_package) GROUP BY ( sy-tabix - 1 ) DIV iv_batch_size + 1. CLEAR <lt_package_data>. "Clear the group "Create the (next) Group <lt_package_data> = VALUE #( FOR ls_group_record IN GROUP ls_package ( CORRESPONDING #( ls_group_record ) ) ). "Process this dataset "Call the background function to process this dataset - Serialize the dataset content before processing process_batch_in_background( iv_batch_data = /ui2/cl_json=>serialize( <lt_package_data> ) ). ENDLOOP. ENDIF.
该代码编译失败,报错信息:"<LT_DATA>" has a generic type that cannot be used for declarations
更新后代码与运行时异常
修改后可编译的代码如下:
FIELD-SYMBOLS: <lt_data> TYPE ANY TABLE. "Dereference the keys data supplied ASSIGN ir_data->* TO <lt_data>. IF sy-subrc EQ 0. FIELD-SYMBOLS: <lt_package_data> TYPE STANDARD TABLE. DATA: lr_data_package_ref TYPE REF TO data. CREATE DATA lr_data_package_ref LIKE <lt_data>. ASSIGN lr_data_package_ref->* TO <lt_package_data>. "Process dataset in batches of size requested LOOP AT <lt_data> ASSIGNING FIELD-SYMBOL(<ls_package>) GROUP BY ( sy-tabix - 1 ) DIV iv_batch_size + 1. CLEAR <lt_package_data>. "Clear the group "Create the (next) Group LOOP AT GROUP <ls_package> ASSIGNING FIELD-SYMBOL(<ls_package_line>). APPEND INITIAL LINE TO <lt_package_data> ASSIGNING FIELD-SYMBOL(<ls_package_record>). <ls_package_record> = <ls_package_line>. ENDLOOP. IF <lt_package_data> IS NOT INITIAL. "Process this dataset "Call the background function to process this dataset process_batch_in_background( iv_batch_data = /ui2/cl_json=>serialize( data = <lt_package_data> ) ). "Serialize the dataset content before processing ENDIF. ENDLOOP. ENDIF.
但该代码在处理包含Packed或Raw类型字段的Sorted Table时,会在ASSIGN lr_data_package_ref->* TO <lt_package_data>.行触发ASSIGN_TYPE_CONFLICT短转储;仅处理字符类型结构的Standard Table时运行正常。
解决思路
匹配表类型的字段符号声明
原代码中<lt_package_data>声明为TYPE STANDARD TABLE,但CREATE DATA lr_data_package_ref LIKE <lt_data>会创建与原表(如Sorted Table)同类型的内表,标准表类型的字段符号无法引用排序表/哈希表,导致类型冲突。需将<lt_package_data>改为兼容的通用类型:FIELD-SYMBOLS: <lt_package_data> TYPE ANY TABLE.若必须用标准表存储批次数据,需显式创建标准表而非继承原表类型:
CREATE DATA lr_data_package_ref TYPE STANDARD TABLE OF LINE OF <lt_data>.处理特殊数据类型的赋值安全
对于Packed/Raw类型字段,直接赋值可能因内存对齐问题报错,改用CORRESPONDING语句确保类型安全:<ls_package_record> = CORRESPONDING #( <ls_package_line> ).优化批次分组的通用性
原GROUP BY依赖sy-tabix,仅对标准表有效(排序表/哈希表的sy-tabix不连续),改用计数器实现通用批次拆分:DATA(lv_counter) = 0. LOOP AT <lt_data> ASSIGNING FIELD-SYMBOL(<ls_line>). lv_counter = lv_counter + 1. APPEND <ls_line> TO <lt_package_data>. IF lv_counter = iv_batch_size OR sy-subrc <> 0. process_batch_in_background( iv_batch_data = /ui2/cl_json=>serialize( data = <lt_package_data> ) ). CLEAR <lt_package_data>. lv_counter = 0. ENDIF. ENDLOOP. IF <lt_package_data> IS NOT INITIAL. process_batch_in_background( iv_batch_data = /ui2/cl_json=>serialize( data = <lt_package_data> ) ). ENDIF.
内容的提问来源于stack exchange,提问作者ArK

