Sql Server Grundlagen für Sharepoint Administratoren
Hibernate Envers - Historisierung mit Hibernate
1. Hibernate Envers
Historisierung mit Hibernate
Essential Bytes Autor 1
2. Envers
Hibernate-Erweiterung für Historisierung
Seit 3.5 Teil von Hibernate Core
Transparente Integration
Muss nicht explizit aufgerufen werden
„Läuft überall wo Hibernate läuft“
Standalone
Application Server
Integriert sich in JPA
Einfache Installation: JAR einbinden, fertig
Essential Bytes Autor 2
3. Vergleich Datenbanklösung
Vorteile gegenüber Triggern, o.ä.
Revisions-Konzept
Unterstützt DB-fremde Konzepte wie eingebettete
Objekte, Klassen-Hierarchien, …
Weniger Aufwand
Einfachster Fall: Eine Annotation pro Klasse
Keine neuen Entity-Klassen notwendig
Gleiche Entities für akt. Daten & History
DB-unabhängig
Einfache aber mächtige Queries
Essential Bytes Autor 3
4. Einfaches Beispiel
@Entity create table Person (
@Audited id bigint not null,
public class Person { name varchar(255),
surname varchar(255),
@Id version bigint,
@GeneratedValue primary key (id)
private long id; );
@Version create table Person_AUD (
private long version; id integer not null,
REV integer not null,
private String name; REVTYPE tinyint,
name varchar(255),
private String surname; surname varchar(255),
primary key (id, REV)
… );
}
Essential Bytes Autor 4
5. Audit-Tabelle
Audit-Suffix (einstellbar)
create table Person_AUD (
id integer not null,
REV integer not null, Revisions-Nummer
Revisions-Typ REVTYPE tinyint,
(ADD, MOD, DEL) name varchar(255),
surname varchar(255),
primary key (id, REV)
);
Essential Bytes Autor 5
6. Erweitertes Mapping
Auditing einzelner Attribute statt ganzer Entity
Jede Menge Annotationen zum Überschreiben von
Defaults
Audit-Tabellen-Name
Ausschließen von Attributen und Relationen
Überschreiben von Einstellungen einer Eltern-Klasse
…
Essential Bytes Autor 6
7. Auditing-Strategien
1) Schnelleres Speichern (Default)
Ein INSERT für jede neue Revision
Vorteil: INSERTs sind schnell
Nachteil: Abfragen von Audit-Informationen häufig nur
mit Subqueries möglich -> Langsam
2) Schnellere Queries
2 Statt 1 Revisions-Attribut: Start- und End-Rev.
Wann immer möglich nur ein UPDATE auf Ende
Vorteil: Schnellere Abfragen von Audit-Infos
Nachteil: UPDATEs sind langsamer als INSERTs
Essential Bytes Autor 7
8. Revisions-Log
Zusätzliche Tabelle
Speichert Informationen zu jeder Revision
Revisions-Nummer
Revisions-Datum
Default-Name: REVINFO
Lässt sich erweitern und anpassen
z.B. um Name des ändernden Benutzers
Essential Bytes Autor 8
9. Erweitertes Logging: Wo?
Abfrage: „Was hat sich in Rev. 42 geändert?“
Standard
Envers muss alle Auditing-Tabellen abfragen
Vorteil: Speichern bleibt gleichschnell
Nachteil: Langsame Abfragen
Alternative
Log speichert Liste mit geänderten Entity-Namen
Vorteil: Schnellere Abfragen
Nachteil: Minimal langsameres Speichern
Essential Bytes Autor 9
10. Erweitertes Logging: Was?
Abfragen:
Welche Attribute wurde von Rev. 42 zu 43 geändert?
Welche Revisionen haben das Attribut „Name“ geändert?
…
Standard:
Geht nicht
Alternative
Logging von geänderten Attributen aktivieren (zusätzliches
Feld in REVINFO mit Liste geänderter Attributs-Namen)
Vorteil: Zusätzliche Abfrage-Möglichkeiten
Nachteil: Minimal langsameres Speichern
Essential Bytes Autor 10
11. Abfragen
Abfragen nur über eigene Query-API
Queries vergleichsweise eingeschränkt (sollte für
Aufgabengebiet aber ausreichen)
Einstieg über AuditReader:
AuditReader reader =
AuditReaderFactory.get(entityManager)
Essential Bytes Autor 11
12. Beispiele
Revisionsnummern einer Entity suchen:
List<Number> revisions =
reader.getRevisions(entityClass, id)
Bestimmte Revision einer Entity suchen:
reader.find(entityClass, id, revision)
Essential Bytes Autor 12
13. Beispiele
Alle Revisionen einer Entity:
List<Person> persons = reader
.createQuery()
.forRevisionsOfEntity(Person.class,
true, false)
.getResultList()
Zu Datum passende Revision:
reader.getRevisionNumberForDate(date)
Essential Bytes Autor 13
14. Beispiele
Revisionen in denen sich das Attribut „Name“ beliebiger
„Person“-Entities geändert hat:
reader.createQuery().
forRevisionsOfEntity(Person.class,
true, false)
.add(
AuditEntity.property("name")
.hasChanged())
.getResultList()
Essential Bytes Autor 14
15. Beispiele
Alle Entities die sich in einer best. Revision geändert
haben:
List<Object> entites = reader
.getCrossTypeRevisionChangesReader()
.findEntities(2)
Essential Bytes Autor 15
16. Einschränkungen
Fehlt, aber ist geplant
Traversal von Relationen in Queries,
also kein „… WHERE country.code = ‘DE‘ “
@Embedded Collections
Fehlt und ist nicht machbar
Auditing von Bags (aka Multimaps)
Essential Bytes Autor 16
17. Nachteile
Etwas schlechtere Performance
Abfragen nur über neue Query-API
Revisions-Log in stark belasteten Systemen
Flaschenhals
Zusätzliche Tabellen
Nachträgliche Integration nicht ganz problemlos
Ein paar Funktionen sind noch experimentell (z.B.
erweitertes Logging)
Essential Bytes Autor 17