[JPA] LockModeTypes

Orolhawion

Aktives Mitglied
Hallo zusammen,

ich versuche mich gerade an konkurrierenden Zugriffen zweier Transactions und das Verhalten bei einem bestimmten Locking Modus verwirrt mich. Es geht um LockModeType.OPTIMISTIC_FORCE_INCREMENT. In der Doku steht dazu folgendes:
WRITE. In this case, the entity manager performs the same optimistic locking operations as for the READ lock mode. However, it also updates the entity's version column.
und
OPTIMISTIC_FORCE_INCREMENT. This is the same as the WRITE lock mode. The WRITE lock mode is still supported in JPA 2.0, but specifying OPTIMISTIC_FORCE_INCREMENT is recommended for new applications.

Wenn ich das richtig verstehe, bedeutet das, dass die @Version-Property der Entity in jedem Fall um eins erhöht wird, auch wenn sich der Zustand der Entity nicht verändert. Dummerweise passiert genau das nicht. Ich benutze folgenden Code:

Java:
tx1.begin();
MyObject mo1 = em.find(MyObject.class, 1);

tx2.begin();
MyObject mo2 = em.find(MyObject.class, 1);

em.lock(mo1, LockModeType.OPTIMISTIC_FORCE_INCREMENT);
em.lock(mo2, LockModeType.OPTIMISTIC_FORCE_INCREMENT);

mo2.setMyAttribute(myValue);
tx2.commit();

mo1.setMyAttribute(anotherValue);
tx1.commit();

Der obige Code beschreibt nur den Ablauf wie ich ihn mit dem Debugger und Breakpoints simuliere.

Obwohl mo2.setMyAttribute(myValue); den Wert nicht verändert (weil myValue halt schon drin steht), würde ich wegen dem LockModeType nun eine Veränderung der @Version-Property nach dem tx2.commit(); erwarten. Das passiert aber nicht, sondern erst nach tx1.commit();

Woran liegt's? Was hab ich evtl. falsch verstanden?
 
M

maki

Gast
Wenn ich das richtig verstehe, bedeutet das, dass die @Version-Property der Entity in jedem Fall um eins erhöht wird, auch wenn sich der Zustand der Entity nicht verändert.
Nein, OPTIMISTIC_FORCE_INCREMENT bedeutet, dass die Version nur hochgezählt wird, wenn die Daten auch in die DB eingetragen werden. So verhindert man eben lost-updates, ohne "teures" pessemistic locking.

Würde sagen, dass der EM schon merkt das es keine Veränderung gab und deswegen das Pseudo-Update am mo2 wegfallen lässt, daher keine DB Änderung und dadurch bleibt das Version field auf dem alten Wert.
Wenn ich in meinem JPA mit EclipseLink und static weaving (!) Testprojekt den bytecode im Decompiler ansehe, dann sehe ich dort, dass aus sowas
Java:
	public void setFirstName(final String firstName) {
		this.firstName = firstName;
	}
Danach sowas wird:

Java:
  public void setFirstName(String firstName)
  {
    _persistence_set_firstName(firstName);
  }
....
public void _persistence_set_firstName(String paramString)
  {
    _persistence_checkFetchedForSet("firstName");
    _persistence_propertyChange("firstName", this.firstName, paramString);
    this.firstName = paramString;
  }
D.h., denselben Wert setzen führt dazu, dass sich für den EM nix geändert hat, und eine SQL Update Query überflüssig wäre.
 

Orolhawion

Aktives Mitglied
Mal angenommen, der EM merkt die "Nichtveränderung" nicht, und initiiert ein SQL-Query mit einem UPDATE, würde dann der Wert der @Version-Property erhöht?
 
M

maki

Gast
Ja, aber eben nur bei echten Veränderungen ;)
Soltest du ja an mo1 nachvollziehen können.
 

Neue Themen


Oben