Ich habe eine Spring Boot 1.3.M1-Webanwendung mit Spring Data JPA. Für optimistisches Sperren mache ich folgendes:
@Version private long version;
. Ich habe anhand der Datenbanktabelle bestätigt, dass dieses Feld richtig inkrementiert wird. version
. version
-Feld als verstecktes Feld oder etwas. Serverseitig, Abrufen einer neuen Kopie der Entität und anschließendes Aktualisieren der gewünschten Felder zusammen mit dem Feld version
. So:
Ich habe erwartet, dass dies eine Ausnahme auslöst, wenn die Versionen nicht übereinstimmen. Aber das tut es nicht. Beim googeln habe ich einige Posts gefunden, die besagen, dass wir die @Vesion
-Eigenschaft einer angehängten Entität nicht wie in der dritten obigen Anweisung festlegen können.
Ich vermute also, dass ich manuell nach der Versionsabweichung suchen muss und die Ausnahme selbst auslösen muss. Wäre das der richtige Weg, oder fehlt mir etwas?
Leider (zumindest für Hibernate) wird das Ändern des @Version
-Feldes nicht zu einer anderen "Version" führen. d. h., die Prüfung der optimistischen Gleichzeitigkeit erfolgt für den Versionswert, der beim Lesen der Entität abgerufen wird, nicht für das Versionsfeld der Entität, wenn diese aktualisiert wird.
z.B.
Das wird funktionieren
%Vor%Dies wird jedoch nicht funktionieren
%Vor% Es gibt einige Möglichkeiten, dies zu umgehen. Der einfachste Weg besteht wahrscheinlich darin, eine optimistische Gleichzeitigkeitsprüfung selbst durchzuführen. Früher hatte ich ein Utility, um die Datenpopulation "DTO to Model" zu erstellen, und ich habe diese Versionsüberprüfungslogik dort abgelegt. Eine andere Möglichkeit besteht darin, die Logik in setVersion()
zu setzen, anstatt die Version tatsächlich zu setzen, die Versionsüberprüfung durchzuführen:
Ein Teil der Antwort @AdrianShum ist korrekt.
Das versionsvergleichende Verhalten folgt grundsätzlich diesen Schritten:
Nehmen Sie nun an, dass die Entität zwischen den Schritten 1 und 3 durch eine andere Transaktion geändert wurde, so dass ihre Versionsnummer in Schritt 3 nicht V1 ist. Dann, da die Versionsnummer unterschiedlich ist, wird die Update-Abfrage keine Registrierung ändern, Hibernate das realisieren und die Ausnahme auslösen.
Sie können dieses Verhalten einfach testen und prüfen, ob die Ausnahme ausgelöst wird und die Versionsnummer zwischen Schritt 1 und 3 direkt in Ihrer Datenbank geändert wird.
Bearbeiten.
Ich weiß nicht, welchen JPA-Persistenzanbieter Sie mit Spring Data JPA verwenden, aber für weitere Details zum optimistischen Sperren mit JPA + Hibernate empfehle ich Ihnen, Kapitel 10, Abschnitt Kontrolle des gleichzeitigen Zugriffs , des Buches
Neben der Antwort von @Adrian Shum möchte ich zeigen, wie ich dieses Problem gelöst habe. Wenn Sie eine Version von Entity manuell ändern und ein Update durchführen möchten, um OptimisticConcurrencyException
zu verursachen, können Sie einfach Entity mit all seinem Feld kopieren, was dazu führt, dass eine Entity ihren Kontext verlässt (wie EntityManager.detach()
). Auf diese Weise verhält es sich richtig.
BEARBEITEN: Die assemblierte Version funktioniert nur, wenn der Ruhezustand-Cache keine Entität mit derselben ID enthält. Dies wird nicht funktionieren:
%Vor%Tags und Links jpa spring-data-jpa hibernate