
RAP - Semantischer Schlüssel
Wofür benötigst du den semantischen Schlüssel und wie wird er im ABAP RESTful Programming Model dargestellt? Hier gibt es mehr dazu.
Inhaltsverzeichnis
In diesem Artikel schauen wir uns den semantischen Schlüssel einmal genauer an, wie er dargestellt wird und was er in unserer Anwendung tut.
Einleitung
Im ABAP RESTful Programming Model setzen wir in unseren Anwendungen vor allem auf UUID Schlüssel um unsere Daten abzulegen. Das erspart uns die Prüfung des eindeutigen Schlüssels, bringt aber nicht nur Vorteile mit sich. Da sich so ein Schlüssel nicht gemerkt werden kann. In solchen Fällen kannst du auf semantische Schlüssel zurückgreifen. Der semantische Schlüssel ist ein eindeutiger und lesbarer Schlüssel innerhalb der Daten, der aber nicht als Schlüsselfeld angelegt wurde. Damit sollten einige Regeln beachtet werden:
- Der Schlüssel kann jederzeit geändert werden
- Die Eindeutigkeit muss durch Prüfungen sichergestellt werden
- Der Schlüssel kann zur Navigation genutzt werden
Darstellung
Schauen wir uns dazu einmal an, wie wir den Schlüssel definieren können. Dazu erweitern wir unsere Anwendung zum Report Pattern um einen semantischen Schlüssel.
Erweiterung
Im Consumption View "ZBS_R_DRPCurrency" müssen wir dazu die Annotation "ObjectModel.semanticKey" aufnehmen. Dazu geben wir alle Elemente an, die zu unserem Schlüssel gehören und diesen eindeutig machen. Dazu der Ausschnitt aus dem View:
@ObjectModel.semanticKey: ['Currency']
define root view entity ZBS_C_DRPCurrency
provider contract transactional_query
as projection on ZBS_R_DRPCurrency
{
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 1.0
@Search.ranking: #HIGH
key Currency,
Ergebnis
Schauen wir uns die Einstiegsseite einmal vor der Definition des neuen semantischen Schlüssels an. Hier sind erst einmal keine Änderungen oder Auffälligkeiten zu erkennen. Jede Spalte in der Tabelle sieht erst einmal gleich aus.
Nachdem wir den Schlüssel gesetzt haben, ändert sich die Liste und der Schlüssel wird fett markiert. Neben der Markierung wird nun auch am Datensatz angezeigt, ob ein Draft dafür verfügbar ist. Vorher war in der Liste nicht ersichtlich, welcher Datensatz im Draft war und musste über den Filter herausgefunden werden.
Navigation
In diesem Abschnitt wollen wir einmal unsere Übersetzungs-App ändern, die mit einer UUID als Schlüssel arbeitet, aber trotzdem einen eindeutigen zusammengesetzten Schlüssel verwendet.
Erweiterung
Dazu erweitern wir den Consumption View "ZBS_C_DMOLanguage", dieses Mal um zwei Felder die den Schlüssel bilden.
@ObjectModel.semanticKey: [ 'SourceLanguage', 'SourceText' ]
define root view entity ZBS_C_DMOLanguage
provider contract transactional_query
as projection on ZBS_R_DMOLanguage
{
key Identification,
SourceLanguage,
SourceText,
Ergebnis
In diesem Fall schauen wir uns einmal die Navigation an. Diese findest du in der URL am Ende des Services. Ohne semantischen Schlüssel, wird der Schlüssel der Entität zur Navigation genutzt.
/Language(Identification=4ae9a11c-f565-1eef-8fe9-2d306bea1dc2,IsActiveEntity=true)
Nachdem wir den semantischen Schlüssel um die beiden Felder erweitert haben, ändert sich auch der Pfad für die Navigation und wir können nun mit lesbaren Schlüsseln zur Entität gelangen.
/Language(SourceText='Apfel',SourceLanguage='DE')
Eindeutigkeit
Wichtig ist nun aber die Eindeutigkeit der Datensätze sicherzustellen. Auf Datenbankebene haben wir keinen Mechanismus definiert, der die Eindeutigkeit prüft oder solche Einträge ablehnt. Damit können wir nun doppelte Datensätze erzeugen.
Daher müssen wir selbst in der Anwendung aktiv werden und eine Validierung implementieren. Dazu erweitern wir unsere Verhaltensdefinition "ZBS_R_DMOLanguage".
validation CheckSemanticKey on save { create; update; field SourceLanguage, SourceText; }
Die Implementierung einer einfachen Prüfung würde daher wie folgt aussehen. Wir lesen im ersten Schritt die zu prüfenden Datensätze, die wir über KEYS erhalten. Dann selektieren wir über unseren Core Data Service mit der lokalen Tabelle als JOIN, um Datensätze mit einer anderen UUID zu erhalten, die aber den gleichen semantischen Schlüssel haben. Das Ergebnis sind dann Datensätze, die bereits mit dem gleichen Schlüssel existieren, daher geben wir für unseren Treffer die Fehlermeldung aus.
READ ENTITIES OF ZBS_R_DMOLanguage IN LOCAL MODE
ENTITY Language FIELDS ( SourceLanguage SourceText ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_selected).
SELECT
FROM ZBS_R_DMOLanguage AS db
INNER JOIN
@lt_selected AS local ON local~Identification <> db~Identification
AND local~SourceLanguage = db~SourceLanguage
AND local~SourceText = db~SourceText
FIELDS db~Identification,
local~Identification AS LocalId
INTO TABLE @DATA(lt_duplicates).
LOOP AT lt_duplicates INTO DATA(ls_duplicate).
INSERT VALUE #( Identification = ls_duplicate-LocalId ) INTO TABLE failed-language.
INSERT VALUE #( Identification = ls_duplicate-LocalId
%msg = new_message_with_text( text = |Semantic key not unique| ) ) INTO TABLE reported-language.
ENDLOOP.
In unserer Fiori App erhalten wir nun eine Fehlermeldung und der Datensatz wird nicht angelegt. Damit kann der Schlüssel erst einmal nur eindeutig angelegt werden.
Vollständiges Beispiel
Die Änderungen an den beiden Anwendungen findest du wie immer im GitHub Repository und im entsprechenden Commit, um alle Änderungen an den Objekten nachvollziehen zu können.
Fazit
Der semantische Schlüssel reichert die App um verschiedene Funktionen an, die uns weitere Informationen geben und die Schlüssel lesbarer machen. Allerdings musst du dich auch darum kümmern, dass die Schlüssel eindeutig bleiben.
Weitere Informationen:
SAP Community - UUID and Semantic Key