ABAP Memory Management: EXPORT, IMPORT, Shared Memory

kategorie
ABAP-Statements
Veröffentlicht
autor
Johannes

Memory Management in ABAP ermöglicht den Datenaustausch zwischen Programmen. Es gibt verschiedene Speicherbereiche: ABAP Memory, SAP Memory, Datenbank-Cluster und Shared Objects.

Speicherbereiche

BereichLebensdauerVerwendung
ABAP MemorySession (Call Stack)Zwischen CALL TRANSACTION
SAP MemoryBenutzer-SessionZwischen Transaktionen
Database ClusterPersistentÜber Sessions hinweg
Shared ObjectsApplikationsserverZwischen Benutzern

Beispiele

1. ABAP Memory (EXPORT/IMPORT TO MEMORY)

" Programm 1: Daten exportieren
DATA: ls_customer TYPE kna1,
lt_orders TYPE TABLE OF vbak.
" Daten vorbereiten
ls_customer-kunnr = '0000001000'.
ls_customer-name1 = 'Mustermann GmbH'.
" In ABAP Memory exportieren
EXPORT customer = ls_customer
orders = lt_orders
TO MEMORY ID 'ZCUSTOMER_DATA'.
" Programm 2: Daten importieren (nach 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: / 'Kunde:', ls_customer-name1.
ENDIF.
" Memory freigeben
FREE MEMORY ID 'ZCUSTOMER_DATA'.

2. SAP Memory (SET/GET PARAMETER)

" SAP Memory für Feldvorbelegung
" Parameter-IDs sind im Data Dictionary definiert
" Wert setzen
SET PARAMETER ID 'KUN' FIELD '0000001000'.
SET PARAMETER ID 'BUK' FIELD '1000'.
" Wert lesen
DATA: lv_kunnr TYPE kunnr,
lv_bukrs TYPE bukrs.
GET PARAMETER ID 'KUN' FIELD lv_kunnr.
GET PARAMETER ID 'BUK' FIELD lv_bukrs.
WRITE: / 'Kunde:', lv_kunnr,
/ 'Buchungskreis:', lv_bukrs.
" Transaktion mit vorbelegten Werten aufrufen
SET PARAMETER ID 'KUN' FIELD '0000001000'.
CALL TRANSACTION 'XD03' AND SKIP FIRST SCREEN.

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

" Persistente Speicherung über Sessions hinweg
" Tabelle: INDX oder eigene Cluster-Tabelle
DATA: ls_settings TYPE ty_settings.
ls_settings-user = sy-uname.
ls_settings-variant = 'DEFAULT'.
ls_settings-values = lt_values.
" In Datenbank speichern
EXPORT settings = ls_settings
TO DATABASE indx(zs) " Tabelle INDX, Area 'ZS'
ID |SETTINGS_{ sy-uname }|. " Eindeutiger Schlüssel
" Später wieder lesen
DATA: ls_settings TYPE ty_settings.
IMPORT settings = ls_settings
FROM DATABASE indx(zs)
ID |SETTINGS_{ sy-uname }|.
IF sy-subrc = 0.
" Settings gefunden
WRITE: / 'Variante:', ls_settings-variant.
ENDIF.
" Löschen
DELETE FROM DATABASE indx(zs)
ID |SETTINGS_{ sy-uname }|.

4. Eigene Cluster-Tabelle

" Tabelle in SE11 anlegen:
" Name: ZCUSTOM_CLUSTER
" Felder:
" - RELID (CHAR 2) - Area
" - SRTFD (CHAR 40) - ID/Schlüssel
" - Cluster-Felder (CLUSTR, CLUSTD)
" Verwendung
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 (Applikationsserver-Cache)

" 1. Area-Klasse definieren (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.
" Wird aufgerufen wenn Area gebaut wird
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. Shared Memory Area in SHMA erstellen
" Name: ZSM_CUSTOMER_CACHE
" Root-Klasse: ZCL_SHARED_AREA
" 3. Verwendung
DATA: lo_area TYPE REF TO zcl_shared_area,
lo_handle TYPE REF TO zcl_sm_customer_cache.
TRY.
" Lesezugriff
lo_handle = zcl_sm_customer_cache=>attach_for_read( ).
lo_area = CAST zcl_shared_area( lo_handle->root ).
" Daten nutzen
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).
" Area existiert noch nicht -> bauen
TRY.
zcl_sm_customer_cache=>build(
EXPORTING
inst_name = zcl_sm_customer_cache=>default_instance
).
CATCH cx_shm_build_error.
ENDTRY.
ENDTRY.

6. Memory zwischen CALL TRANSACTION

" Hauptprogramm
DATA: ls_order TYPE vbak.
ls_order-vbeln = '0000000001'.
ls_order-kunnr = '0000001000'.
" Daten für gerufenes Programm bereitstellen
EXPORT order = ls_order TO MEMORY ID 'ZORDER_EDIT'.
" Transaktion aufrufen
CALL TRANSACTION 'ZORDER_CHANGE'.
" Nach Rückkehr: Geänderte Daten lesen
IMPORT order = ls_order FROM MEMORY ID 'ZORDER_EDIT'.
FREE MEMORY ID 'ZORDER_EDIT'.
" Gerufenes Programm (ZORDER_CHANGE)
DATA: ls_order TYPE vbak.
IMPORT order = ls_order FROM MEMORY ID 'ZORDER_EDIT'.
" Bearbeitung...
" Geänderte Daten zurückgeben
EXPORT order = ls_order TO MEMORY ID 'ZORDER_EDIT'.
LEAVE PROGRAM.

7. Memory Helper Klasse

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.
" Verwendung
" 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.
" Daten gefunden
ENDIF.
" Database
zcl_memory_helper=>save_to_db(
iv_id = |USER_{ sy-uname }_SETTINGS|
iv_data = ls_settings
).

8. Benutzer-spezifische Einstellungen

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.
" Defaults
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.
" Verwendung
DATA(lo_settings) = NEW zcl_user_settings( ).
DATA(ls_settings) = lo_settings->load( ).
" Einstellungen ändern
ls_settings-pagesize = 50.
lo_settings->save( ls_settings ).

9. Session-übergreifender Cache

" Shared Memory für häufig benötigte Stammdaten
" Area Root Klasse
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.
" Cache nach 1 Stunde invalidieren
rv_expired = xsdbool(
lv_now - mv_loaded_at > 3600
).
ENDMETHOD.
ENDCLASS.
" Verwendung
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.
" Cache-Validität prüfen
IF lo_cache->is_expired( ).
lo_handle->detach( ).
zcl_sm_material=>invalidate_instance( ).
" Beim nächsten Zugriff wird neu gebaut
ELSE.
DATA(ls_material) = lo_cache->get_material( lv_matnr ).
lo_handle->detach( ).
ENDIF.
CATCH cx_shm_attach_error.
" Fallback: Direkt aus DB
SELECT SINGLE * FROM mara
WHERE matnr = @lv_matnr
INTO @ls_material.
ENDTRY.

10. EXPORT/IMPORT mit Kompression

" Für große Datenmengen: Kompression
DATA: lt_big_table TYPE TABLE OF vbak,
lv_xstring TYPE xstring.
" Daten in komprimiertes XString
EXPORT data = lt_big_table
TO DATA BUFFER lv_xstring
COMPRESSION ON.
" In DB speichern
UPDATE zcache SET data = lv_xstring
WHERE id = lv_id.
" Wieder laden
SELECT SINGLE data FROM zcache
WHERE id = @lv_id
INTO @lv_xstring.
IMPORT data = lt_big_table
FROM DATA BUFFER lv_xstring.

11. Memory im Fehlerfall freigeben

" TRY-CLEANUP für sauberes Aufräumen
DATA: lv_memory_id TYPE c LENGTH 30 VALUE 'ZTEMP_DATA'.
TRY.
EXPORT data = ls_data TO MEMORY ID lv_memory_id.
" Verarbeitung die fehlschlagen kann
process_data( ).
" Normal freigeben
FREE MEMORY ID lv_memory_id.
CATCH cx_root INTO DATA(lx_error).
" Auch im Fehlerfall freigeben
FREE MEMORY ID lv_memory_id.
RAISE EXCEPTION lx_error.
ENDTRY.
" Oder mit CLEANUP
TRY.
EXPORT data = ls_data TO MEMORY ID lv_memory_id.
process_data( ).
CLEANUP.
" Wird bei Exception automatisch ausgeführt
FREE MEMORY ID lv_memory_id.
ENDTRY.

12. Datenübertragung an Report

" Hauptprogramm: Daten an Report übergeben
DATA: lt_selections TYPE TABLE OF rsparams.
" Daten exportieren
EXPORT selections = lt_selections
TO MEMORY ID 'ZREPORT_DATA'.
" Report aufrufen
SUBMIT zreport_process AND RETURN.
" Ergebnis abholen
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.
" Daten vom Aufrufer
IMPORT selections = lt_selections
FROM MEMORY ID 'ZREPORT_DATA'.
" Verarbeitung...
" Ergebnis zurückgeben
EXPORT results = lt_results
TO MEMORY ID 'ZREPORT_RESULTS'.

Speicherbereich-Übersicht

MethodeSyntaxBereich
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_AREAApplikationsserver

Wichtige Hinweise / Best Practice

  • FREE MEMORY aufrufen wenn Daten nicht mehr benötigt.
  • Eindeutige IDs verwenden (z.B. mit Programm/User).
  • ABAP Memory nur innerhalb eines Call Stacks.
  • SAP Memory für Feldvorbelegung (Parameter-IDs).
  • Database Cluster für persistente Daten.
  • Shared Objects für Server-weites Caching.
  • COMPRESSION ON für große Datenmengen.
  • CLEANUP für Aufräumen bei Exceptions.
  • Memory-IDs nicht zu lang (max. 72 Zeichen).
  • Kombinieren Sie mit Background Jobs für Datenübergabe.