We're updating the issue view to help you get more done. 

PESSIMISTIC_WRITE doesn't autoFlush before find/lock

Description

Code [0] fails with [1]. I am just trying to pesimistically lock an entity in the same transaction where I created it.

The cause is:
1) Entity has SEQUENCE id generator, Hibernate doesn't flush before the find() nor before the lock().
2) With PESSIMISTIC_WRITE Hibernate has to issue SELECT FOR UPDATE.

Because entity is not inserted at the time of the SELECT FOR UPDATE, the find/lock fails....

Currently I workaround this by flushing before acquiring the pessimistic lock.

[0]

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package cz.nguyen; import java.sql.SQLException; import javax.persistence.*; public class Main { private static EntityManagerFactory emf; @Entity public static class Employee { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private Long id; } public static void main(String[] args) throws SQLException { emf = Persistence.createEntityManagerFactory("default"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Employee e = new Employee(); em.persist(e); em.find(Employee.class, 1l, LockModeType.PESSIMISTIC_WRITE); // Same behavior with: // em.lock(e, LockModeType.PESSIMISTIC_WRITE); em.close(); emf.close(); } }

[1]

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Exception in thread "main" javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [cz.nguyen.entity.Employee#1] at org.hibernate.internal.ExceptionConverterImpl.wrapStaleStateException(ExceptionConverterImpl.java:202) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:88) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:176) at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3431) at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3381) at cz.nguyen.Main.main(Main.java:27) Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [cz.nguyen.entity.Employee#1] at org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy.lock(PessimisticWriteSelectLockingStrategy.java:76) at org.hibernate.persister.entity.AbstractEntityPersister.lock(AbstractEntityPersister.java:1802) at org.hibernate.event.internal.AbstractLockUpgradeEventListener.upgradeLock(AbstractLockUpgradeEventListener.java:82) at org.hibernate.event.internal.DefaultLoadEventListener.loadFromSessionCache(DefaultLoadEventListener.java:566) at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:441) at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219) at org.hibernate.event.internal.DefaultLoadEventListener.lockAndLoad(DefaultLoadEventListener.java:403) at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:124) at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1239) at org.hibernate.internal.SessionImpl.access$1900(SessionImpl.java:203) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.doLoad(SessionImpl.java:2797) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2778) at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3407) ... 2 more

Environment

None

Status

Assignee

Unassigned

Reporter

Filip Nguyen

Fix versions

None

Labels

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Affects versions

5.2.11

Priority

Critical