Numbering in RAP definiert, wann und wie Primärschlüssel für neue Business-Object-Instanzen vergeben werden. Die Wahl zwischen Early und Late Numbering hat direkte Auswirkungen auf die Architektur Ihrer Anwendung.
Grundkonzept
| Strategie | Zeitpunkt | Schlüssel verfügbar | Anwendungsfall |
|---|---|---|---|
| Early Numbering | Bei CREATE | Sofort nach Anlage | Standard für die meisten Szenarien |
| Late Numbering | Bei SAVE | Erst nach Speicherung | Externe Number Ranges, Legacy-Systeme |
Wann welche Strategie?
Early Numbering wählen, wenn:
- Der Schlüssel sofort nach der Anlage benötigt wird
- Child-Entities direkt referenziert werden müssen
- Die Nummer aus einer internen Number Range kommt
- Sie ein Managed Szenario ohne Legacy-Abhängigkeiten haben
Late Numbering wählen, wenn:
- Die Nummer von einem externen System vergeben wird
- Eine externe Number Range verwendet wird (z.B. Belegnummern)
- Die Nummernvergabe erst beim Speichern erfolgen darf
- Draft-Szenarien mit späteren Nummernzuweisungen benötigt werden
Early Numbering
Bei Early Numbering wird der Schlüssel direkt beim CREATE vergeben. Das Framework übernimmt die Nummernvergabe automatisch oder Sie implementieren sie selbst.
Managed Early Numbering
Das einfachste Szenario: Das Framework vergibt automatisch UUIDs oder Sie nutzen Number Ranges.
managed implementation in class zbp_i_travel unique;strict ( 2 );
define behavior for ZI_Travel alias Travelpersistent table ztravellock masterauthorization master ( instance )etag master LastChangedAt{ create; update; delete;
// Automatische Nummernvergabe durch das Framework (UUID) field ( numbering : managed ) TravelUUID;
// Alternative: Schlüssel ist readonly, wird in Determination gesetzt field ( readonly ) TravelId;}Early Numbering mit Number Range
Für fortlaufende Nummern aus einer Number Range:
managed implementation in class zbp_i_travel unique;strict ( 2 );
define behavior for ZI_Travel alias Travelpersistent table ztravellock masterauthorization master ( instance )etag master LastChangedAtearly numbering{ create; update; delete;
// Readonly, da früh vergeben field ( readonly ) TravelId;}Implementation der Early Numbering
CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler. PRIVATE SECTION. METHODS earlynumbering_create FOR NUMBERING IMPORTING entities FOR CREATE Travel.ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD earlynumbering_create. DATA: lv_travel_id TYPE /dmo/travel_id.
" Number Range Object und Intervall DATA(lv_nr_object) = 'ZTRAVEL'. DATA(lv_nr_interval) = '01'.
LOOP AT entities INTO DATA(ls_entity) WHERE TravelId IS INITIAL. TRY. " Nummer aus Number Range holen cl_numberrange_runtime=>number_get( EXPORTING nr_range_nr = lv_nr_interval object = lv_nr_object IMPORTING number = DATA(lv_number) ).
lv_travel_id = lv_number.
" Mapping: %cid -> generierter Schlüssel APPEND VALUE #( %cid = ls_entity-%cid %key = ls_entity-%key %is_draft = ls_entity-%is_draft TravelId = lv_travel_id ) TO mapped-travel.
CATCH cx_number_ranges INTO DATA(lx_nr). " Fehler bei Nummernvergabe APPEND VALUE #( %cid = ls_entity-%cid %key = ls_entity-%key %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = lx_nr->get_text( ) ) ) TO reported-travel.
APPEND VALUE #( %cid = ls_entity-%cid %key = ls_entity-%key ) TO failed-travel. ENDTRY. ENDLOOP. ENDMETHOD.
ENDCLASS.Late Numbering
Bei Late Numbering wird der Schlüssel erst beim Speichern vergeben. Bis dahin arbeitet das System mit temporären IDs (%pid - preliminary ID).
Anwendungsfälle für Late Numbering
- Externe Number Ranges die nur beim Commit verfügbar sind
- Legacy-Systeme die Nummern bei der Speicherung vergeben
- Belegnummern die erst bei finaler Buchung entstehen
- Draft-Szenarien wo die finale Nummer erst bei Aktivierung vergeben wird
Late Numbering Behavior Definition
managed implementation in class zbp_i_travel unique;strict ( 2 );
define behavior for ZI_Travel alias Travelpersistent table ztravellock masterauthorization master ( instance )etag master LastChangedAtlate numbering{ create; update; delete;
// Schlüssel wird erst bei SAVE vergeben field ( readonly ) TravelId;}Implementation der Late Numbering
CLASS lsc_travel DEFINITION INHERITING FROM cl_abap_behavior_saver. PROTECTED SECTION. METHODS adjust_numbers REDEFINITION.ENDCLASS.
CLASS lsc_travel IMPLEMENTATION.
METHOD adjust_numbers. DATA: lv_travel_id TYPE /dmo/travel_id.
" Number Range Object und Intervall DATA(lv_nr_object) = 'ZTRAVEL'. DATA(lv_nr_interval) = '01'.
" Alle neuen Einträge ohne finale Nummer LOOP AT mapped-travel ASSIGNING FIELD-SYMBOL(<ls_travel>) WHERE %is_draft = if_abap_behv=>mk-off.
IF <ls_travel>-TravelId IS INITIAL. TRY. " Nummer aus Number Range holen cl_numberrange_runtime=>number_get( EXPORTING nr_range_nr = lv_nr_interval object = lv_nr_object IMPORTING number = DATA(lv_number) ).
" Finale Nummer zuweisen <ls_travel>-TravelId = lv_number.
CATCH cx_number_ranges INTO DATA(lx_nr). " Fehlerbehandlung RAISE SHORTDUMP lx_nr. ENDTRY. ENDIF. ENDLOOP. ENDMETHOD.
ENDCLASS.Late Numbering mit Draft
Bei Draft-Szenarien mit Late Numbering arbeitet der Draft mit einer vorläufigen ID. Die finale Nummer wird erst bei Aktivierung vergeben:
managed implementation in class zbp_i_travel unique;strict ( 2 );with draft;
define behavior for ZI_Travel alias Travelpersistent table ztraveldraft table zdraft_travellock master total etag LastChangedAtauthorization master ( instance )etag master LastChangedAtlate numbering{ create; update; delete;
field ( readonly ) TravelId;
draft action Edit; draft action Activate optimized; draft action Discard; draft action Resume; draft determine action Prepare;}Managed vs Unmanaged Numbering
Managed Numbering
Das Framework übernimmt die komplette Nummernvergabe:
define behavior for ZI_Travel alias Travel{ // UUID wird automatisch generiert field ( numbering : managed ) TravelUUID;}Vorteile:
- Kein Code erforderlich
- Garantiert eindeutige UUIDs
- Sofort verfügbar (Early)
Nachteile:
- Nur UUIDs möglich
- Keine sprechenden Nummern
Unmanaged Numbering (Early)
Sie implementieren die Nummernvergabe selbst bei CREATE:
define behavior for ZI_Travel alias Travelearly numbering{ field ( readonly ) TravelId;}Vorteile:
- Volle Kontrolle über Nummernformat
- Number Ranges möglich
- Schlüssel sofort verfügbar
Nachteile:
- Mehr Implementierungsaufwand
- Sie müssen Eindeutigkeit sicherstellen
Unmanaged Numbering (Late)
Sie implementieren die Nummernvergabe beim SAVE:
define behavior for ZI_Travel alias Travellate numbering{ field ( readonly ) TravelId;}Vorteile:
- Externe Number Ranges möglich
- Nummern erst bei Commit
- Lückenlose Nummernfolge möglich
Nachteile:
- Schlüssel während der Transaktion nicht bekannt
- Komplexere Referenzierung von Child-Entities
- %pid-Handling erforderlich
Umgang mit %pid (Preliminary ID)
Bei Late Numbering verwendet das Framework eine vorläufige ID (%pid), bis die finale Nummer vergeben wird:
" CREATE mit Late NumberingMODIFY ENTITIES OF zi_travel ENTITY Travel CREATE FIELDS ( AgencyId CustomerId ) WITH VALUE #( ( %cid = 'CID_1' " TravelId ist noch nicht bekannt! AgencyId = '000001' CustomerId = '000010' ) ) MAPPED DATA(mapped) FAILED DATA(failed) REPORTED DATA(reported).
" Mapped enthält %pid statt finalem Schlüssel" mapped-travel[ 1 ]-%pid ist gesetzt" mapped-travel[ 1 ]-TravelId ist initial
" Erst nach COMMIT ENTITIES ist TravelId gesetztCOMMIT ENTITIES.Child-Entities mit Late Numbering
Bei Parent-Child-Beziehungen mit Late Numbering:
" Behavior Definitiondefine behavior for ZI_Travel alias Travellate numbering{ association _Booking { create; }}
define behavior for ZI_Booking alias Booking{ // Booking referenziert Travel über %pid}" EML: Create Parent und Child gleichzeitigMODIFY ENTITIES OF zi_travel ENTITY Travel CREATE FIELDS ( AgencyId CustomerId ) WITH VALUE #( ( %cid = 'TRAVEL_1' AgencyId = '000001' CustomerId = '000010' ) )
CREATE BY \_Booking FIELDS ( BookingId FlightDate ) WITH VALUE #( ( %cid_ref = 'TRAVEL_1' " Referenz auf Parent via %cid %target = VALUE #( ( %cid = 'BOOKING_1' BookingId = '0001' FlightDate = sy-datum ) ) ) ) MAPPED mapped FAILED failed REPORTED reported.Entscheidungsmatrix
| Kriterium | Early + Managed | Early + Unmanaged | Late |
|---|---|---|---|
| UUID als Schlüssel | ✅ Ideal | ❌ | ❌ |
| Number Range (intern) | ❌ | ✅ Ideal | ⚠️ Möglich |
| Number Range (extern) | ❌ | ❌ | ✅ Ideal |
| Schlüssel sofort verfügbar | ✅ | ✅ | ❌ |
| Child-Referenzierung | Einfach | Einfach | Via %pid |
| Implementierungsaufwand | Minimal | Mittel | Höher |
| Legacy-Integration | ❌ | ⚠️ | ✅ Ideal |
Best Practices
- Managed Numbering als Standard - Nutzen Sie UUID und
numbering : managedwenn möglich - Early Numbering für Number Ranges - Wenn Sie sprechende Nummern brauchen, aber die Nummer sofort verfügbar sein soll
- Late Numbering nur wenn nötig - Nur bei externen Systemen oder speziellen Anforderungen
- %cid konsequent nutzen - Besonders wichtig bei Late Numbering für Parent-Child-Referenzen
- Fehlerbehandlung - Number Ranges können Fehler werfen (Overflow, Lock)
- Testbarkeit - Late Numbering erschwert Unit Tests, da Schlüssel erst spät bekannt sind
Weiterführende Themen
- RAP Grundlagen - Einführung in das RESTful ABAP Programming Model
- Draft Handling in RAP - Zwischenspeicherung für komplexe Workflows
- RAP Actions und Functions - Geschäftslogik implementieren