ABAP Memory Management: EXPORT, IMPORT, Shared Memory

Kategorie
ABAP-Statements
Veröffentlicht
Autor
Johannes

Memory Management en ABAP permite el intercambio de datos entre programas. Existen diferentes áreas de almacenamiento: ABAP Memory, SAP Memory, Database-Cluster y Shared Objects.

Áreas de almacenamiento

ÁreaDuraciónUso
ABAP MemorySesión (Call Stack)Entre CALL TRANSACTION
SAP MemorySesión de usuarioEntre transacciones
Database ClusterPersistenteA través de sesiones
Shared ObjectsServidor de aplicaciónEntre usuarios

Ejemplos

1. ABAP Memory (EXPORT/IMPORT TO MEMORY)

" Programa 1: Exportar datos
DATA: ls_customer TYPE kna1,
lt_orders TYPE TABLE OF vbak.
" Preparar datos
ls_customer-kunnr = '0000001000'.
ls_customer-name1 = 'Mustermann GmbH'.
" Exportar a ABAP Memory
EXPORT customer = ls_customer
orders = lt_orders
TO MEMORY ID 'ZCUSTOMER_DATA'.
" Programa 2: Importar datos (después de CALL TRANSACTION)
DATA: ls_customer TYPE kna1,
lt_orders TYPE TABLE OF vbak.
IMPORT customer = ls_customer
orders = lt_orders
FROM MEMORY ID 'ZCUSTOMER_DATA'.
IF sy-subrc = 0.
WRITE: / 'Cliente:', ls_customer-name1.
ENDIF.
" Liberar memoria
FREE MEMORY ID 'ZCUSTOMER_DATA'.

2. SAP Memory (SET/GET PARAMETER)

" SAP Memory para prerrellenado de campos
" Los Parameter-IDs están definidos en el Data Dictionary
" Establecer valor
SET PARAMETER ID 'KUN' FIELD '0000001000'.
SET PARAMETER ID 'BUK' FIELD '1000'.
" Leer valor
DATA: lv_kunnr TYPE kunnr,
lv_bukrs TYPE bukrs.
GET PARAMETER ID 'KUN' FIELD lv_kunnr.
GET PARAMETER ID 'BUK' FIELD lv_bukrs.
WRITE: / 'Cliente:', lv_kunnr,
/ 'Sociedad:', lv_bukrs.
" Llamar transacción con valores prerrellenados
SET PARAMETER ID 'KUN' FIELD '0000001000'.
CALL TRANSACTION 'XD03' AND SKIP FIRST SCREEN.

3. Database-Cluster (EXPORT/IMPORT TO DATABASE)

" Almacenamiento persistente a través de sesiones
" Tabla: INDX u otra tabla cluster propia
DATA: ls_settings TYPE ty_settings.
ls_settings-user = sy-uname.
ls_settings-variant = 'DEFAULT'.
ls_settings-values = lt_values.
" Guardar en base de datos
EXPORT settings = ls_settings
TO DATABASE indx(zs) " Tabla INDX, Area 'ZS'
ID |SETTINGS_{ sy-uname }|. " Clave única
" Leer más tarde
DATA: ls_settings TYPE ty_settings.
IMPORT settings = ls_settings
FROM DATABASE indx(zs)
ID |SETTINGS_{ sy-uname }|.
IF sy-subrc = 0.
" Settings encontrados
WRITE: / 'Variante:', ls_settings-variant.
ENDIF.
" Eliminar
DELETE FROM DATABASE indx(zs)
ID |SETTINGS_{ sy-uname }|.

4. Tabla Cluster propia

" Crear tabla en SE11:
" Nombre: ZCUSTOM_CLUSTER
" Campos:
" - RELID (CHAR 2) - Area
" - SRTFD (CHAR 40) - ID/Clave
" - Campos cluster (CLUSTR, CLUSTD)
" Uso
EXPORT data = ls_data
TO DATABASE zcustom_cluster(AA)
ID lv_key.
IMPORT data = ls_data
FROM DATABASE zcustom_cluster(AA)
ID lv_key.

5. Shared Objects (Cache del servidor de aplicación)

" 1. Definir clase de área (SE24)
CLASS zcl_shared_area DEFINITION
PUBLIC FINAL
CREATE PUBLIC
SHARED MEMORY ENABLED.
PUBLIC SECTION.
INTERFACES: if_shm_build_instance.
DATA: mt_customers TYPE HASHED TABLE OF kna1 WITH UNIQUE KEY kunnr.
METHODS: load_customers.
ENDCLASS.
CLASS zcl_shared_area IMPLEMENTATION.
METHOD if_shm_build_instance~build.
" Se llama cuando se construye el área
DATA(lo_area) = CAST zcl_shared_area( bound_memory ).
lo_area->load_customers( ).
ENDMETHOD.
METHOD load_customers.
SELECT * FROM kna1
INTO TABLE mt_customers
UP TO 10000 ROWS.
ENDMETHOD.
ENDCLASS.
" 2. Crear Shared Memory Area en SHMA
" Nombre: ZSM_CUSTOMER_CACHE
" Clase raíz: ZCL_SHARED_AREA
" 3. Uso
DATA: lo_area TYPE REF TO zcl_shared_area,
lo_handle TYPE REF TO zcl_sm_customer_cache.
TRY.
" Acceso de lectura
lo_handle = zcl_sm_customer_cache=>attach_for_read( ).
lo_area = CAST zcl_shared_area( lo_handle->root ).
" Usar datos
READ TABLE lo_area->mt_customers INTO DATA(ls_customer)
WITH KEY kunnr = '0000001000'.
lo_handle->detach( ).
CATCH cx_shm_attach_error INTO DATA(lx_error).
" El área no existe aún -> construir
TRY.
zcl_sm_customer_cache=>build(
EXPORTING
inst_name = zcl_sm_customer_cache=>default_instance
).
CATCH cx_shm_build_error.
ENDTRY.
ENDTRY.

6. Memory entre CALL TRANSACTION

" Programa principal
DATA: ls_order TYPE vbak.
ls_order-vbeln = '0000000001'.
ls_order-kunnr = '0000001000'.
" Proporcionar datos para programa llamado
EXPORT order = ls_order TO MEMORY ID 'ZORDER_EDIT'.
" Llamar transacción
CALL TRANSACTION 'ZORDER_CHANGE'.
" Después del retorno: Leer datos modificados
IMPORT order = ls_order FROM MEMORY ID 'ZORDER_EDIT'.
FREE MEMORY ID 'ZORDER_EDIT'.
" Programa llamado (ZORDER_CHANGE)
DATA: ls_order TYPE vbak.
IMPORT order = ls_order FROM MEMORY ID 'ZORDER_EDIT'.
" Edición...
" Devolver datos modificados
EXPORT order = ls_order TO MEMORY ID 'ZORDER_EDIT'.
LEAVE PROGRAM.

7. Clase Helper de Memory

CLASS zcl_memory_helper DEFINITION.
PUBLIC SECTION.
" ABAP Memory
CLASS-METHODS: export_to_memory
IMPORTING iv_id TYPE clike
iv_data TYPE any.
CLASS-METHODS: import_from_memory
IMPORTING iv_id TYPE clike
EXPORTING ev_data TYPE any
RETURNING VALUE(rv_found) TYPE abap_bool.
CLASS-METHODS: free_memory
IMPORTING iv_id TYPE clike.
" SAP Memory
CLASS-METHODS: set_parameter
IMPORTING iv_id TYPE clike
iv_value TYPE clike.
CLASS-METHODS: get_parameter
IMPORTING iv_id TYPE clike
RETURNING VALUE(rv_value) TYPE string.
" Database Cluster
CLASS-METHODS: save_to_db
IMPORTING iv_id TYPE clike
iv_data TYPE any.
CLASS-METHODS: load_from_db
IMPORTING iv_id TYPE clike
EXPORTING ev_data TYPE any
RETURNING VALUE(rv_found) TYPE abap_bool.
CLASS-METHODS: delete_from_db
IMPORTING iv_id TYPE clike.
ENDCLASS.
CLASS zcl_memory_helper IMPLEMENTATION.
METHOD export_to_memory.
EXPORT data = iv_data TO MEMORY ID iv_id.
ENDMETHOD.
METHOD import_from_memory.
IMPORT data = ev_data FROM MEMORY ID iv_id.
rv_found = xsdbool( sy-subrc = 0 ).
ENDMETHOD.
METHOD free_memory.
FREE MEMORY ID iv_id.
ENDMETHOD.
METHOD set_parameter.
SET PARAMETER ID iv_id FIELD iv_value.
ENDMETHOD.
METHOD get_parameter.
GET PARAMETER ID iv_id FIELD rv_value.
ENDMETHOD.
METHOD save_to_db.
DATA(lv_id) = CONV indx_srtfd( iv_id ).
EXPORT data = iv_data TO DATABASE indx(zm) ID lv_id.
COMMIT WORK.
ENDMETHOD.
METHOD load_from_db.
DATA(lv_id) = CONV indx_srtfd( iv_id ).
IMPORT data = ev_data FROM DATABASE indx(zm) ID lv_id.
rv_found = xsdbool( sy-subrc = 0 ).
ENDMETHOD.
METHOD delete_from_db.
DATA(lv_id) = CONV indx_srtfd( iv_id ).
DELETE FROM DATABASE indx(zm) ID lv_id.
COMMIT WORK.
ENDMETHOD.
ENDCLASS.
" Uso
" ABAP Memory
zcl_memory_helper=>export_to_memory(
iv_id = 'MY_DATA'
iv_data = ls_data
).
IF zcl_memory_helper=>import_from_memory(
iv_id = 'MY_DATA'
IMPORTING ev_data = ls_data
) = abap_true.
" Datos encontrados
ENDIF.
" Database
zcl_memory_helper=>save_to_db(
iv_id = |USER_{ sy-uname }_SETTINGS|
iv_data = ls_settings
).

8. Configuraciones específicas de usuario

CLASS zcl_user_settings DEFINITION.
PUBLIC SECTION.
TYPES: BEGIN OF ty_settings,
layout TYPE string,
pagesize TYPE i,
filters TYPE string,
END OF ty_settings.
METHODS: constructor
IMPORTING iv_program TYPE sy-repid DEFAULT sy-repid.
METHODS: load
RETURNING VALUE(rs_settings) TYPE ty_settings.
METHODS: save
IMPORTING is_settings TYPE ty_settings.
METHODS: delete.
PRIVATE SECTION.
DATA: mv_id TYPE indx_srtfd.
ENDCLASS.
CLASS zcl_user_settings IMPLEMENTATION.
METHOD constructor.
mv_id = |{ iv_program }_{ sy-uname }|.
ENDMETHOD.
METHOD load.
IMPORT settings = rs_settings
FROM DATABASE indx(us)
ID mv_id.
IF sy-subrc <> 0.
" Valores predeterminados
rs_settings-pagesize = 100.
ENDIF.
ENDMETHOD.
METHOD save.
EXPORT settings = is_settings
TO DATABASE indx(us)
ID mv_id.
COMMIT WORK.
ENDMETHOD.
METHOD delete.
DELETE FROM DATABASE indx(us) ID mv_id.
COMMIT WORK.
ENDMETHOD.
ENDCLASS.
" Uso
DATA(lo_settings) = NEW zcl_user_settings( ).
DATA(ls_settings) = lo_settings->load( ).
" Modificar configuraciones
ls_settings-pagesize = 50.
lo_settings->save( ls_settings ).

9. Cache compartido entre sesiones

" Shared Memory para datos maestros frecuentemente necesarios
" Clase raíz del área
CLASS zcl_material_cache DEFINITION
PUBLIC FINAL
CREATE PUBLIC
SHARED MEMORY ENABLED.
PUBLIC SECTION.
INTERFACES: if_shm_build_instance.
TYPES: ty_materials TYPE HASHED TABLE OF mara WITH UNIQUE KEY matnr.
DATA: mt_materials TYPE ty_materials,
mv_loaded_at TYPE timestampl.
METHODS: get_material
IMPORTING iv_matnr TYPE matnr
RETURNING VALUE(rs_material) TYPE mara.
METHODS: is_expired
RETURNING VALUE(rv_expired) TYPE abap_bool.
ENDCLASS.
CLASS zcl_material_cache IMPLEMENTATION.
METHOD if_shm_build_instance~build.
DATA(lo_root) = CAST zcl_material_cache( bound_memory ).
SELECT * FROM mara
INTO TABLE lo_root->mt_materials
WHERE mtart IN ('FERT', 'HALB', 'ROH').
GET TIME STAMP FIELD lo_root->mv_loaded_at.
ENDMETHOD.
METHOD get_material.
READ TABLE mt_materials INTO rs_material
WITH KEY matnr = iv_matnr.
ENDMETHOD.
METHOD is_expired.
DATA: lv_now TYPE timestampl.
GET TIME STAMP FIELD lv_now.
" Invalidar cache después de 1 hora
rv_expired = xsdbool(
lv_now - mv_loaded_at > 3600
).
ENDMETHOD.
ENDCLASS.
" Uso
DATA: lo_handle TYPE REF TO zcl_sm_material,
lo_cache TYPE REF TO zcl_material_cache.
TRY.
lo_handle = zcl_sm_material=>attach_for_read( ).
lo_cache = lo_handle->root.
" Verificar validez del cache
IF lo_cache->is_expired( ).
lo_handle->detach( ).
zcl_sm_material=>invalidate_instance( ).
" En el próximo acceso se reconstruirá
ELSE.
DATA(ls_material) = lo_cache->get_material( lv_matnr ).
lo_handle->detach( ).
ENDIF.
CATCH cx_shm_attach_error.
" Fallback: Directamente de BD
SELECT SINGLE * FROM mara
WHERE matnr = @lv_matnr
INTO @ls_material.
ENDTRY.

10. EXPORT/IMPORT con compresión

" Para grandes volúmenes de datos: Compresión
DATA: lt_big_table TYPE TABLE OF vbak,
lv_xstring TYPE xstring.
" Datos en XString comprimido
EXPORT data = lt_big_table
TO DATA BUFFER lv_xstring
COMPRESSION ON.
" Guardar en BD
UPDATE zcache SET data = lv_xstring
WHERE id = lv_id.
" Cargar nuevamente
SELECT SINGLE data FROM zcache
WHERE id = @lv_id
INTO @lv_xstring.
IMPORT data = lt_big_table
FROM DATA BUFFER lv_xstring.

11. Liberar memoria en caso de error

" TRY-CLEANUP para limpieza ordenada
DATA: lv_memory_id TYPE c LENGTH 30 VALUE 'ZTEMP_DATA'.
TRY.
EXPORT data = ls_data TO MEMORY ID lv_memory_id.
" Procesamiento que puede fallar
process_data( ).
" Liberar normalmente
FREE MEMORY ID lv_memory_id.
CATCH cx_root INTO DATA(lx_error).
" También liberar en caso de error
FREE MEMORY ID lv_memory_id.
RAISE EXCEPTION lx_error.
ENDTRY.
" O con CLEANUP
TRY.
EXPORT data = ls_data TO MEMORY ID lv_memory_id.
process_data( ).
CLEANUP.
" Se ejecuta automáticamente en Exception
FREE MEMORY ID lv_memory_id.
ENDTRY.

12. Transferencia de datos a Report

" Programa principal: Pasar datos a Report
DATA: lt_selections TYPE TABLE OF rsparams.
" Exportar datos
EXPORT selections = lt_selections
TO MEMORY ID 'ZREPORT_DATA'.
" Llamar report
SUBMIT zreport_process AND RETURN.
" Recuperar resultado
DATA: lt_results TYPE ty_result_tab.
IMPORT results = lt_results
FROM MEMORY ID 'ZREPORT_RESULTS'.
FREE MEMORY ID 'ZREPORT_DATA'.
FREE MEMORY ID 'ZREPORT_RESULTS'.
" Report (ZREPORT_PROCESS)
DATA: lt_selections TYPE TABLE OF rsparams,
lt_results TYPE ty_result_tab.
" Datos del llamador
IMPORT selections = lt_selections
FROM MEMORY ID 'ZREPORT_DATA'.
" Procesamiento...
" Devolver resultado
EXPORT results = lt_results
TO MEMORY ID 'ZREPORT_RESULTS'.

Resumen de áreas de almacenamiento

MétodoSintaxisÁrea
EXPORT TO MEMORYID ‘xyz’ABAP Memory
SET PARAMETERID ‘PAR’SAP Memory
EXPORT TO DATABASEindx(xx) ID ‘xyz’DB Cluster
EXPORT TO DATA BUFFERxstringVariable
Shared MemoryCL_SHM_AREAServidor de aplicación

Notas importantes / Mejores prácticas

  • Llamar FREE MEMORY cuando los datos ya no se necesiten.
  • Usar IDs únicos (p. ej. con programa/usuario).
  • ABAP Memory solo dentro de un Call Stack.
  • SAP Memory para prerrellenado de campos (Parameter-IDs).
  • Database Cluster para datos persistentes.
  • Shared Objects para caching a nivel de servidor.
  • COMPRESSION ON para grandes volúmenes de datos.
  • CLEANUP para limpieza en Exceptions.
  • IDs de memoria no muy largos (máx. 72 caracteres).
  • Combinar con Background Jobs para transferencia de datos.