Historisierung

IFS-Logo 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.

Creative Commons Namensnennung 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 wird der Datenzugriff verlangsamt, da in diesem Fall immer zwei Tabellen statt einer geschrieben werden.

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.

Tabelle 1. DAO-Erweiterung (Bearbeitungshistorie): Lesen der zum Datum gültigen Entität

Schema

<Entity> lese<Entity>(<Schlüssel>, Calendar)`

Beispiel

AkteDao leseAkte(id, Calendar)

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.

Tabelle 2. DAO-Erweiterung (Bearbeitungshistorie): Lesen der aktuell gültigen Entität

Schema

<Entity> lese<Entity>(<Schlüssel>)`

Beispiel

AkteDao leseAkte(id)

2.2.3. Neue Methode: Lesen der gesamten Historie

Diese Methode liefert die gesamte Historie eines Datensatzes.

Tabelle 3. DAO-Erweiterung (Bearbeitungshistorie): Lesen der gesamten Historie einer Entität

Schema

List<Entität> lese<Entität>Historie(Schlüssel)

Beispiel

List<AkteDao> leseAkteHistorie(id)

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.

Tabelle 4. DAO-Erweiterung (Bearbeitungshistorie): Erzeugen einer neuen Version einer Entität

Schema

Entität erzeugeNeueVersion(Entität)

Beispiel

AkteDao erzeugeNeueVersion(Akte)

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.

Tabelle 5. DAO-Erweiterung (Bearbeitungshistorie): Setzen einer maximalen Anzahl von Versionen

Schema

MAX_EINTRAEGE_HISTORIE

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.

historisierung beispiel ausgangslage.dn
Abbildung 1. Modellierung der Entitäten ohne Historisierung

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.

historisierung beispiel historisiert.dn
Abbildung 2. Modellierung des Bestands mit Historisierung

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.

historisierung beispiel dao ausgangslage.dn
Abbildung 3. Modellierung des DAO ohne Historisierung

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:

historisierung beispiel dao historisiert.dn
Abbildung 4. Modellierung des DAO mit Historisierung

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.