Artikel

 
Juli 2009 | Artikel

Automatische Historisierung mit Hibernate Envers

(Link zum Artikel: http://www.it-republik.de/jaxenter/artikel/2477)

Aus der Geschichte lernen

Text: Hansjörg Wingeier, Stefan Wohlgemuth und Patrick Brügger
  • Teilen
  • kommentieren
  • empfehlen
  • Bookmark and Share
In vielen Branchen müssen auf Grund gesetzlicher Vorgaben Mutationen von Daten nachvollziehbar sein. Das heißt, es muss für jeden vergangenen Zeitpunkt möglich sein, den damaligen Stand der Daten zu ermitteln. Allgemein wird das als Auditing oder Historisierung der Daten bezeichnet. Umgesetzt in einer Applikation bedeutet das, dass anstelle des Löschens von Datensätzen diese irgendwie als "gelöscht" markiert werden müssen oder auch dass eine einfache Mutation eines Datensatzes sicherstellen muss, dass der alte Zustand in irgendeiner Art vorhanden bleibt.
Teil 1   Teil 2   Teil 3   

Der Standardbenutzer arbeitet in erster Linie mit den aktuellen Daten. Für ihn ist es daher wichtig, dass durch die Historisierung die Performance nicht merklich sinkt. Für einen Applikationsentwickler sollte die Historisierung der Daten möglichst transparent erfolgen. Er möchte sich nicht explizit darum kümmern müssen, er erwartet, dass das verwendete Framework diese Aufgabe automatisch erledigt. Dieser Artikel zeigt, wie diese Anforderungen mit Envers umgesetzt werden können.

Die Entstehung von Envers

Das Projekt Envers (Entity Versioning) wurde von Adam Warski im Jahr 2008 ins Leben gerufen. In seinen Anfängen – namentlich als Preview-Versionen – war Envers befähigt, einfache Properties wie Strings, Numbers und Dates zu versionieren. Später wurde dann das Audit von 1:1- und 1:n-Relationen unterstützt.

Ab dem Envers-1.0.0Beta1-Release konnten Queries auf den historisierten Daten ausgeführt werden. Es war damit möglich, den Zustand einer Entität auf Grund einer Revisionsnummer abzufragen oder die Zustandsentwicklung einer Entität über ihre gesamte Lebensdauer zu verfolgen. Die Envers 1.0.0GA-Version wurde im Juli 2008 veröffentlicht. Sie stellte eine stabile Version der bis dahin entwickelten Features zusammen. Version 1.1.0GA erschien im Oktober 2008. Nebst Codeverbesserungen und Bugfixes lag der Fokus dieses Release in der Unterstützung von persistenten Collections. Mit den steten Verbesserungen im Laufe der Zeit und der zunehmenden Akzeptanz war es nicht weiter verwunderlich, dass Envers Ende Oktober 2008 ein offizielles Hibernate-Modul wurde. Im Frühjahr 2009 erschien die Version 1.2.0GA. Diese enthält in erster Linie die Änderungen, die den Wechsel zu einem offiziellen Hibernate-Modul nötig machten. Die erste offizielle Hibernate-Core-Version, die das Envers-Modul integriert hat, wird Version 3.4.0 GA sein.

Was ist Envers?

Envers ist eine Zusatzbibliothek zu Hibernate, die sich um das Auditieren der Daten kümmert. Das bemerkenswerte an Envers ist, dass es das Auditieren praktisch völlig transparent geschehen lässt. So können Daten, wie mit Hibernate üblich, gelesen und mutiert werden. Ebenso muss das bestehende Datenbankschema nicht verändert, sondern nur durch zusätzliche Tabellen ergänzt werden. Wie im Folgenden gezeigt wird, sind auch die notwendigen Anpassungen im Code nur minimal.

Funktionsweise

Soll eine persistente Klasse (eine mit @Entity annotierte Klasse) auditiert werden, so muss diese zusätzlich mit der Annotation @Audited versehen werden (Listing 1).

  1. @Entity
  2. @Audited
  3. public class Person {
  4. @Id
  5. @GeneratedValue
  6. private int id;
  7. private String name;
  8. ...
  9. }
Listing 1: Eine persistente Klasse wird auditiert

Zur Laufzeit wird dann für jede dieser Klassen eine entsprechende Audit-Entität erstellt. Diese dient als Container für die historisierten Daten. Die gleiche Abbildung findet auch auf der Datenbank statt. Zum Beispiel wird für eine Tabelle PERSON eine entsprechende PERSON_AUD-Tabelle erstellt. In der Datenbank sind somit die aktuellen Daten komplett von den historisierten Daten getrennt (Listing 2).

  1. create table Person (
  2. id integer not null,
  3. name varchar(255),
  4. surname varchar(255),
  5. C_VERSION_NUM bigint,
  6. primary key (id)
  7. );
  8. create table Person_AUD (
  9. id integer not null,
  10. REV integer not null,
  11. REVTYPE tinyint,
  12. name varchar(255),
  13. surname varchar(255),
  14. primary key (id, REV)
  15. );
Listing 2: Auszug aus dem DB-Skript

Ähnlich wie bei Subversion werden alle in einer Transaktion durchgeführten Änderungen mit der gleichen globalen Revisionsnummer versehen. Jede Revision definiert also einen konsistenten Zustand der Daten.

Teil 1   Teil 2   Teil 3   

Anzeige

Kommentare


Anzeige

zurück zum Seitenanfang