2016-05-16 2 views
0

Ich habe ein Problem, wo ich eine Sperre für die Zeile mit der get(Serializable,Class,LockOptions) Methode mit der LockOptions.UPGRADE erwerben.Hibernate: Lädt das Objekt nach get() mit LockOptions.UPGRADE

Das Objekt, auf dem die Sperre erreicht wird, ist bereits in der Sitzung vorhanden. Nach Ausführung von Select ... für Update, finde ich, dass, wenn die entsprechende Zeile in der Tabelle nach dem ersten Abruf des Objekts und vor der get(Serializable,Class,LockOptions) geändert wurde, die Methode ein aktualisiertes Objekt nicht zurückgibt.

Ich möchte Folgendes klären, Ist dies, weil ich versuche, Sperre für eine Zeile, deren Objekt bereits im Sitzungscache geladen ist.

Löscht Hibernate gerade einen select ... for update im Hintergrund, lädt das Objekt jedoch nicht neu, sondern ruft stattdessen einen aus dem Sitzungscache ab, wenn er gefunden wird?

Im Folgenden ist das Code-Snippet darüber, wie ich Sperre erwerbe.

List<MyObject> listOfMyObject = dao.getListOfMyObjects(); 

for(MyObject m : listOfMyObject){ 
    m = session.get(id,MyObject.class,LockOptions.UPGRADE); 
    // 
} 

Der Sperrmechanismus funktioniert einwandfrei. Während die Sperre durch die ThreadOne-Transaktion gehalten wird, kann ich sehen, dass die andere ThreadTwo-Transaktion darauf wartet, eine Sperre zu erhalten. Wenn die ThreadOne-Transaktion die Sperre jetzt freigibt, erhält die zweite Transaktion sie über die Methode session.get(id,MyObject.class,LockOptions.UPGRADE). Das zurückgegebene Objekt verfügt nicht über den von ThreadOne aktualisierten Wert.

Antwort

0

Im Idealfall, wenn Sie LockOptions.Upgrade verwenden, ist es eine Art pessimistisches Sperren.

Es sollte idealerweise nicht zulassen, dass eine andere Transaktion den Datensatz ändert, weil es eine Art pessimistische Sperre für diese Datenbankzeile darstellt.

Idealerweise sollten Sie statt pessimistischem Sperren Optimistisches Sperren verwenden, indem Sie eine Art Versions-/Timestamp-Spalte verwenden, in der Sie programmgesteuert mehr Kontrolle haben.

0

Ja, nach Hibernate docs lädt session.get(Serializable,Class,LockOptions) die Instanz aus der Sitzung, wenn sie bereits existiert. Für Ihre Situation möchten Sie wahrscheinlich session.refresh(Object object) direkt nach session.get(Serializable,Class,LockOptions) verwenden, um den Status der Instanz erneut aus der Datenbank zu lesen.