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(); } }