It appears that EntityTransaction.commit() does not release a pessimistic lock -> test code below.
I tried it in with the current (2.7.6_01) and older versions (2.6.9, 2.5.7, 2.4.7) with the same result.
(side note: EntityTransaction.rollback() releases it correctly)
// Account.java
package icke;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Account {
@Id
private int no;
private int balance;
public Account(int n) {
no = n;
balance = 1000;
}
public int getNo() {
return no;
}
public int getBalance() {
return balance;
}
public void credit(int a) {
balance += a;
}
}
// Main.java
package icke;
import javax.persistence.*;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
try {
testLocking();
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void testLocking() {
// persist
EntityManagerFactory emf = Persistence.createEntityManagerFactory("accounts.odb");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(new Account(0));
em.getTransaction().commit();
// update
EntityManager em1 = emf.createEntityManager();
em1.getTransaction().begin();
Account a1 = em1.find(Account.class, 0, LockModeType.PESSIMISTIC_WRITE);
a1.credit(10);
em1.getTransaction().commit();
System.out.println(em1.getLockMode(a1)); // -> PESSIMISTIC_WRITE
// try to retrieve again
EntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();
Account a2 = em2.find(Account.class, 0, LockModeType.PESSIMISTIC_READ); // -> LockTimeoutException
System.out.println(a2.getBalance());
em2.getTransaction().commit();
}
}