FirstSpirit benutzt UUIDs für die eindeutige Identifikation von Datensätzen. Diese UUIDs, im folgenden GIDs genannt, werden beispielsweise für die Verlinkung von Datensätzen verwendet, wenn diese nicht über eine Fremdschlüsselbeziehung in der Datenbank abgebildet werden und auch für die Identifikation von Datensätzen, wenn diese mittels Content Transport in ein Projekt eingespielt werden (gibt es einen Datensatz mit derselben GID, so wird dieser aktualisiert, ansonsten wird ein neuer Datensatz angelegt).
Aus technischen Gründen werden diese GIDs an zwei Stellen gespeichert. Einmal in der Spalte FS_GID an dem Datensatz selber und einmal in einer Backend Datenbank genannt Registry.
Die Fehlermeldung
java.lang.IllegalStateException: GID mismatch detected for entity '<GID>, de.espirit.or.impl.IdentifierImpl$TemporalIdentifierUC@9584076e{<TABELLENNAME>,FS_ID=<FS_ID>,FS_VALID_FROM=<TIMESTAMP>,FS_VALID_TO=<TIMESTAMP, meistens 9223372036854775807>,FS_RELEASE_TO=<TIMESTAMP, meistens 0 oder 9223372036854775807>}', expected: EntityGidEntry[<andere GID> | schema=<ID des Schemas>, dbTable=<TABELLENNAME>, id=<FS_ID>]
bedeutet nun, dass die am Datensatz gespeicherte GID (in der Fehlermeldung als <GID> bezeichnet) nicht der GID in der Registry (in der Fehlermeldung als <andere GID> bezeichnet) entspricht.
Mögliche Ursachen
- Die Datensätze wurden in der Datenbank direkt gelöscht und der Transaction-Counter des Schemas wurde zurückgesetzt (auch dieser wird als Wert in der Datenbank gespeichert).
- Der eingesetzte Datenbanktreiber modifiziert die GIDs beim Speichern. Bekannt ist dies, wenn die PostgreSQL 9 Datenbank verwendet wird und ein PostgreSQL 8 Treiber.
Auswirkungen
- In diesem Fall tritt der Fehler jedesmal auf, wenn in einer Tabelle ein Datensatz neu angelegt wird, für den bereits eine GID in der Registry gespeichert ist. Das führt zu dem Eindruck, dass das Problem sporadisch auftreten würde, was aber so nicht ganz korrekt ist.
- Jedesmal, wenn ein Datensatz (und somit seine GID) sich nicht mehr im Cache der Datenbank-Anbindung befindet, kommt es beim Speichern von Änderungen an diesem Datensatz zu einem Fehler.
Lösungen
- Es muss dafür gesorgt werden, dass keine Datensätze mehr angelegt werden mit IDs, für die bereits eine GID gespeichert ist. Dies kann entweder erreicht werden, indem der Wert für den Transaction-Counter so erhöht wird, dass die neuen Datensätze mit ausreichend hohen FS_IDs angelegt werden, oder indem aus der Registry die nun fehlerhaften GIDs gelöscht werden. Bitte erstellen Sie ein Ticket bei unserem Technical Support, um die Anleitung für die für Sie am besten passende Lösung zu bekommen.
- Der Datenbanktreiber muss aktualisiert werden auf eine zur Datenbank passende Version. Sofern möglich, sollten alle vorhandenen Datensätze gelöscht werden, da nicht sichergestellt werden kann, dass neben der UUID weitere Daten beim Speichern modifiziert wurden (auch wenn dies unwahrscheinlich ist). Sollte dies nicht möglich sein, so sollten für alle Datensätze neue GIDs vergeben werden, nachdem sichergestellt wurde, dass der neue Treiber das Problem behebt. Nutzen Sie dafür das folgende Skript:
import de.espirit.firstspirit.agency.StoreAgent;
import de.espirit.firstspirit.access.store.Store;
import de.espirit.firstspirit.common.GidAgent;
import de.espirit.firstspirit.access.store.contentstore.Content2;
storeAgent = context.requestSpecialist(StoreAgent.TYPE);
contentStore = storeAgent.getStore(Store.Type.CONTENTSTORE);
gidAgent = context.requireSpecialist(GidAgent.TYPE);
storeElements = contentStore.getChildren(Content2.class,true);
storeElementCounter = storeElements.iterator();
while (storeElementCounter.hasNext()) {
content2 = storeElementCounter.next();
schema = content2.getSchema();
try {
orSession = gidAgent.migrateSchema(schema);
select = orSession.createSelect(content2.getEntityType().getName());
entityList = orSession.executeQuery(select);
context.logInfo("EntityList.size(): " + entityList.size().toString());
gidAdaptionResult = gidAgent.adaptGid(schema, entityList, true);
context.logInfo("gidAdaptionResult.size(): " + gidAdaptionResult.size().toString());
} catch (Exception e) {
context.logError("ERROR: "+e);
}
}