Historisierung
Diese Seite ist ein Teil der IsyFact-Standards. Alle Inhalte der Seite, insbesondere Texte und Grafiken, sind urheberrechtlich geschützt. Alle urheberrechtlichen Nutzungs- und Verwertungsrechte liegen beim Bundesverwaltungsamt.
Die Nutzung ist unter den Lizenzbedingungen der Creative Commons Namensnennung 4.0 International gestattet.
Die technische Umsetzung der Historisierung mit JPA gliedert sich in zwei Aspekte: die Umsetzung des Gültigkeitszeitraums und der Bearbeitungshistorie.
1. Umsetzung des Gültigkeitszeitraums
Jeder Datensatz, für den ein Gültigkeitszeitraum definiert werden soll, definiert zwei neue Datumsattribute: gueltigVon
und gueltigBis
.
Anforderungen an die Datumsattribute gibt es seitens der IsyFact nicht.
Sie werden vollständig durch die fachlichen Anforderungen der Anwendung bestimmt.
2. Umsetzung der Bearbeitungshistorie
Das im Konzept zur Historisierung motivierte Entwurfsmuster wird im Folgenden beschrieben.
2.1. Schritt 1: Ergänzen von Datumsattributen
Historisierte Versionen und die aktuelle Version eines Datensatzes werden in der gleichen Tabelle gepflegt.
Dazu wird die Tabelle um zwei neue Datumsattribute erweitert: aktuellVon
und aktuellBis
.
Der aktuell gültige Datensatz ist somit der mit dem neuesten aktuellVon
-Datum.
Das aktuellBis
-Datum vereinfacht den Zugriff auf die Tabelle per SQL.
Es wird dadurch einfacher, den Datensatz zu finden, der zu einem bestimmten Datum aktuell war.
Das Attribut aktuellBis
des aktuellen Datensatzes wird per Konvention auf das Datum 31.12.9999 gesetzt.
Damit kann dieses Attribut zur Ermittlung des aktuellen Datensatzes genutzt werden.
Anwendungen können festlegen, dass dieses Attribut Teil des fachlichen Schlüssels ist. Dadurch ist es möglich, die Tabelle der Datenbank zu partitionieren, um die Verarbeitungsgeschwindigkeit zu erhöhen.
In Ausnahmefällen darf auch eine eigene Tabelle zur Speicherung der Historie angelegt werden. Dadurch werden Schreiboperationen verlangsamt, da immer in zwei Tabellen statt in eine geschrieben wird.
Durch das Einführen der Datumsattribute erweitert sich der fachliche Schlüssel des Datensatzes. Der somit aus mehreren Attributen zusammengesetzte fachliche Schlüssel wird genauso behandelt, wie jeder andere zusammengesetzte fachliche Schlüssel auch.
2.2. Schritt 2: Erweiterung des Data Access Objects
Alle Zugriffe auf Entitäten werden gemäß Referenzarchitektur über das zugehörige Data Access Object (DAO) vorgenommen.
Im Rahmen der Historisierung muss das DAO auch dafür sorgen, dass die Attribute aktuellVon
und aktuellBis
mit den korrekten Werten belegt sind.
Es wird wie folgt angepasst und erweitert.
2.2.1. Neue Methode: Lesen der zum Datum gültigen Entität
Die Funktion liefert die zum übergebenen Zeitpunkt (Parameter Calendar
) gültige Entität.
Schema |
|
---|---|
Beispiel |
|
2.2.2. Ändern der Methode zum Lesen der aktuellen Entität
Diese Methode ist im DAO bereits vorhanden.
Sie wird so angepasst, dass sie das aktuell gültige Objekt zurückgibt.
Dies ist das Objekt mit den übergebenen Schlüsselattributen, dessen aktuellBis
-Eintrag der 31.12.9999 ist.
Schema |
|
---|---|
Beispiel |
|
2.2.3. Neue Methode: Lesen der gesamten Historie
Diese Methode liefert die gesamte Historie eines Datensatzes.
Schema |
|
---|---|
Beispiel |
|
2.2.4. Neue Methode: Erzeugen einer neuen Version
Bei einer Umsetzung ohne Historisierung konnten Objekte direkt über ihren Konstruktor erzeugt und mithilfe der Methode zum Speichern persistiert werden.
Dies ist jetzt nicht mehr möglich, da in diesem Fall die Attribute aktuellVon
und aktuellBis
nicht korrekt belegt
werden würden.
Daher bietet das DAO eine Methode an, um auf Basis eines bestehenden Objekts eine neue Version dieses Objekts zu erstellen.
Die Idee dabei ist, dass das bisher aktuelle Objekt einen Nachfolger erhält.
Schema |
|
---|---|
Beispiel |
|
Bei der bisher aktuellen Entität wird vermerkt, dass sie nicht mehr aktuell ist und die neu erzeugte Entität wird als aktuelle Entität gekennzeichnet. Im Detail werden dabei die folgenden Schritte durchgeführt:
- Ausgangslage
-
Die bisher aktuelle Entität wird als Parameter übergeben.
- Schritt 1
-
Der Zeitstempel der übergebenen Entität wird verändert und damit diese Entität als nicht mehr aktuell markiert. Die übergebene Entität ist die bisher aktuelle Entität, dessen Zeitstempel
aktuellBis
bisher auf den 31.12.9999 gesetzt war. Dieser Zeitstempel wird auf den aktuellen Zeitpunkt gesetzt. - Schritt 2
-
Es wird eine neue Entität erzeugt.
- Schritt 3
-
Der Zeitstempel
aktuellVon
der neuen Entität wird auf den aktuellen Zeitstempel gesetzt. - Schritt 4
-
Die Daten der übergebenen Entität werden in die neue Entität kopiert.
- Schritt 5
-
Der Zeitstempel
aktuellBis
der neuen Entität wird auf den 31.12.9999 gesetzt. Damit ist sie als die aktuelle Entität gekennzeichnet. - Schritt 6
-
Das neue Objekt wird in der Session des Entity Managers registriert, damit es beim späteren Commit persistiert wird.
Als Parameter der Methode darf auch null
übergeben werden.
In diesem Fall wird ein neuer, leerer Datensatz angelegt, dessen Zeitstempel aber korrekt befüllt sind.
Dies ist nötig, um das erste Objekt einer Historie erzeugen zu können.
Nach konkretem Bedarf kann die Methode zur Erzeugung einer neuen Version durch zusätzliche "Convenience"-Methoden ergänzt werden, die andere Parameter erwarten. Beispiele dafür sind eine Methode, die als Parameter nur die Schlüsselwerte der Entität und nicht die Entität selbst erwartet oder eine Methode, welche die aktuellste Version einer Entität selbst ermittelt.
Optionale Erweiterung: Falls eine Obergrenze für die Anzahl der zu historisierenden Datensätze vorgegeben ist, wird die Einhaltung dieser Obergrenze ebenfalls durch das DAO sichergestellt.
In diesem Fall wird bei der Erzeugung einer neuen Version geprüft, ob dadurch die Obergrenze überschritten wird und ggf. die älteste Version gelöscht.
Der Wert dieser Obergrenze wird in einer Klassenkonstante des DAOs gehalten.
Diese Klassenkonstante ist öffentlich, damit deren Wert bei einer Veränderung der Historie außerhalb des DAOs berücksichtigt werden kann.
Sie trägt den Namen MAX_EINTRAEGE_HISTORIE
.
Schema |
|
---|
2.2.5. Löschen der Methode zum Speichern einer Entität
Es ist nicht mehr möglich, ein neues Objekt zu erzeugen und direkt in der Datenbank zu speichern und damit die Historisierung zu umgehen.
Es wurden in der Schnittstelle des DAOs bewusst keine Funktionen vorgesehen, um die Historie verändern zu können. Der Regelfall ist der, dass die Zeitstempel automatisch durch das DAO gesetzt und die Historie nicht mehr verändert wird.
Eine Veränderung der Historie ist technisch nicht ausgeschlossen. Dies kann durch die direkte Bearbeitung der historisierten Datensätze geschehen. Dies ist allerdings ein fachlicher Ausnahmefall. Im Regelfall darf die Historie nicht verändert werden.
2.3. Beispiel
Das fachliche Szenario für dieses Beispiel ist: Für eine Ware sollen, je nach Datum, ein Rabatt gelten.
2.3.1. Schritt 1: Ergänzen von Datumsattributen
Waren und Preise sind ohne Historisierung wie in Modellierung der Entitäten ohne Historisierung modelliert.
Die Entität Ware
repräsentiert eine konkrete Ware, deren fachlicher Schlüssel die ean
ist.
Der Rabatt ist in einer separaten Entität Rabatt
modelliert und kann auf viele Waren gleichzeitig angewendet werden.
Demnach ist die Relation zwischen Rabatt
und Ware
eine 1-zu-n-Relation.
Dies ist wichtig für die Historisierung, damit keine Waren redundant gespeichert werden, wenn sich die Rabatte ändern.
In die Entität Rabatt
werden nun die Attribute aktuellVon
und aktuellBis
eingefügt.
Dies ist in Modellierung des Bestands mit Historisierung dargestellt.
2.3.2. Schritt 2: Erweiterung des Data Access Objects
Das DAO für die Entität Rabatt
ohne Historisierung ist in Modellierung des DAO ohne Historisierung dargestellt.
Um einen neuen Rabatt
zu persistieren, wird eine Instanz von Bestand erzeugt und anschließend speichereRabatt(Rabatt)
aufgerufen.
Die Methode leseRabatt(String)
liest einen Rabatt
, der durch den übergebenen String, den Namen, identifiziert wird.
Die Methode loescheRabatt(Rabatt)
löscht den Rabatt aus der Datenbank.
Um mit Rabatten eine Historisierung umzusetzen, werden die folgenden Erweiterungen vorgenommen, wie in Modellierung des DAO mit Historisierung dargestellt:
Die neuen Methoden erzeugeNeueVersion(Rabatt)
, leseRabatt(String, Calendar)
sowie leseBestandHistorie(String)
wurden eingefügt.
Die Methode leseRabatt(String)
wurde geändert, sodass der aktuelle Datensatz geliefert wird.
Eine Methode, speichereRabatt(Rabatt)
, wurde entfernt.