Worum es geht
Ein Modell ist entweder auditiert oder nicht. Auditiert heißt: CDMS hebt bei jeder Änderung eines Objekts den neuen Stand auf. So ein gespeicherter Stand heißt Revision. Alle Revisionen eines Objekts zusammen sind seine Historie.
Ob ein Modell auditiert ist, entscheidet ein einziger Schalter am Modell: im Hub „Auditing: ja“, in einer Modelldatei auditing: true. Der Schalter gilt für das ganze Modell. Einzelne Felder kannst du nicht ausnehmen.
Der Zeitstrahl eines Objekts
So sieht die Historie eines Auftrags aus, der angelegt, zweimal geändert, einmal zurückgesetzt und dann gelöscht wird:
flowchart LR
A["Revision 17 · ADD<br/>POST /create<br/>price 90.8"] --> B["Revision 42 · MOD<br/>PATCH<br/>price 120.5"]
B --> C["Revision 51 · MOD<br/>PUT<br/>price 99.0"]
C --> D["Revision 58 · MOD<br/>Rollback auf 17<br/>price 90.8"]
D --> E["Revision 63 · DEL<br/>DELETE"]
Jede Revision hat eine Art, im JSON revisionType:
| Art | Bedeutung | Was die Revision enthält |
|---|---|---|
ADD | das Objekt wurde angelegt | den Stand direkt nach dem Anlegen |
MOD | das Objekt wurde geändert | den Stand direkt nach der Änderung |
DEL | das Objekt wurde gelöscht | nur die id, alle anderen Felder sind leer |
Die Nummern steigen, sind aber nicht lückenlos. Dazwischen liegen Revisionen anderer Objekte. Mehr dazu unter Was eine Revision festhält.
Welche Operation welche Revision erzeugt
| Operation | Revision |
|---|---|
POST /create | ADD |
PUT /update/{id}, PATCH /update/{id} | MOD, auch wenn sich fachlich nichts ändert, denn _updatedOn wird neu gesetzt |
| neuer Dateiinhalt bei einem Datei-Modell | MOD, weil sich fileVersion, Größe und Typ ändern |
POST /{id}/rollback/{revision} | MOD mit dem alten Inhalt, siehe Auf einen alten Stand zurücksetzen |
DELETE /delete/{id} | DEL |
| Kind wird im selben Request mit angelegt, geändert oder gelöscht | eine eigene ADD-, MOD- oder DEL-Revision für das Kind, wenn sein Modell auditiert ist |
| nur eine Liste des Objekts ändert sich | MOD für das Objekt mit der Liste |
| lesen, suchen, Historie lesen, herunterladen | keine Revision |
Die Revisionen entstehen erst, wenn die Anfrage erfolgreich zu Ende geht. Scheitert sie, wird mit allem anderen auch die Revision verworfen. Siehe Ein Request, eine Transaktion.
Eine Anfrage, eine Revisionsnummer
Ändert eine Anfrage mehrere Objekte, bekommen alle Änderungen dieselbe Revisionsnummer. Ein Auftrag mit drei neuen Positionen, in einem Request angelegt, ergibt also eine Revision 17, und darin stehen der Auftrag und die drei Positionen, jeweils als ADD.
Das gilt je Datenbank. Berührt eine Anfrage Modelle in der System-Datenbank und in der Mandanten-Datenbank, entsteht in jeder Datenbank eine eigene Revision mit eigener Nummer. Siehe Keine Atomarität über zwei Datenbanken.
Auditiert oder nicht
| Modell auditiert? | Anfrage schreibt? | Anfrage erfolgreich? | Ergebnis |
|---|---|---|---|
| nein | – | – | keine Revision, es gibt nur den aktuellen Stand |
| ja | nein | – | keine Revision, Lesen wird nicht aufgezeichnet |
| ja | ja | nein | keine Revision, die Änderung wurde verworfen |
| ja | ja | ja | neue Revision ADD, MOD oder DEL |
- jede Änderung wird eine Revision
- Historie und Rollback sind möglich, wenn die Endpunkte eingetragen sind
- bei Datei-Modellen bleibt jeder alte Inhalt als Version
- die Datenbank bekommt zu jeder Tabelle eine Audit-Tabelle
hibernate-enverskommt in die POM
- nur der aktuelle Stand
- keine Historie, kein Rollback, auch wenn die Endpunkte eingetragen sind
- ein neuer Dateiinhalt überschreibt den alten
- nach dem Löschen bleibt nichts
Was im Hintergrund passiert
Du musst das nicht wissen, um die API zu benutzen. Es hilft aber, wenn du in die Datenbank schaust:
-
1HubDas Modell ist auf „Auditing: ja“ gestellt.
-
2BuildDer Generator schreibt
@Auditedan die Entity-Klasse und nimmthibernate-enversin die POM auf.Envers ist die Bibliothek, die Revisionen schreibt. Siehe Der Projektrahmen. -
3DatenbankZu jeder Tabelle des Modells gibt es eine Audit-Tabelle
<tabelle>_AUD, dazu einmal je Datenbank die Tabellerevinfo. -
4CDMS→DatenbankBei jedem erfolgreichen Schreiben legt Envers eine Zeile in
revinfoan und für jedes geänderte Objekt eine Zeile in dessen_AUD-Tabelle.Ergebnis:revinfosagt wer, wann und von wo. Die_AUD-Zeile hält den Stand des Objekts.
Die Endpunkte zum Lesen der Historie und zum Zurücksetzen entstehen nur, wenn das Modell auditiert ist und sie in der Endpunkt-Liste stehen. Siehe Welche Endpunkte ein Modell hat.
Besondere Fälle
Wann: Ein Modell mit bestehenden Daten wird auf auditiert gestellt und neu generiert.
Die Historie beginnt mit der ersten Änderung danach. Für ein bestehendes Objekt ist die erste Revision dann ein MOD, ein ADD gibt es nicht. Ältere Stände kennt CDMS nicht, und auf sie kannst du auch nicht zurücksetzen.
Wann: Ein auditiertes Modell wird auf nicht auditiert gestellt.
Neue Änderungen werden nicht mehr aufgezeichnet, und die Endpunkte für Historie und Rollback entfallen. Was bis dahin aufgezeichnet wurde, bleibt in der Datenbank, ist über die API aber nicht mehr erreichbar.
Wann: Ein auditiertes Modell hat eine Beziehung zu einem anderen Modell.
Das Zielmodell muss ebenfalls auditiert sein. Envers weist ein auditiertes Modell ab, das auf ein nicht auditiertes zeigt, und die Anwendung startet dann nicht. Modelle, die miteinander verbunden sind, auditierst du deshalb gemeinsam.
Fallen
Wie es weitergeht
- Was in einer Revision steht: Was eine Revision festhält
- Revisionen abrufen: Historie lesen
- Auf einen alten Stand zurück: Auf einen alten Stand zurücksetzen
- Was nach dem Löschen bleibt: Was nach dem Löschen bleibt