OptimisticLockException after lock, refresh, merge in a transaction in Hibernate

Solution Verified - Updated -

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP) 7
  • Hibernate 5

Issue

The following steps involving update of an entity with a @Version property in a transaction result in an OptimisticLockException during commit.

  1. Employee e = entityManager.find(Employee.class, THE_KEY_HERE);
  2. entityManager.lock(e, LockModeType.READ);
  3. entityManager.refresh(e);
  4. Update some property of the entity (and merge)
  5. Commit
... javax.persistence.OptimisticLockException: Newer version [2] of entity [[support.hibernate.entity.Employee#THE_KEY_HERE]] found in database
    at org.hibernate.internal.ExceptionConverterImpl.wrapLockException(ExceptionConverterImpl.java:247)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:103)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
    at org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:60)
    ... 29 more
Caused by: org.hibernate.OptimisticLockException: Newer version [2] of entity [[support.hibernate.entity.Employee#THE_KEY_HERE]] found in database
    at org.hibernate.action.internal.EntityVerifyVersionProcess.doBeforeTransactionCompletion(EntityVerifyVersionProcess.java:51)
    at org.hibernate.engine.spi.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:954)
    at org.hibernate.engine.spi.ActionQueue.beforeTransactionCompletion(ActionQueue.java:525)
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2487)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:473)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:178)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:39)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:271)
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104)
    ...

Resolution

This issue1 is resolved in EAP 7.2 cumulative patch (CP) 4 and later releases. Production systems should use the latest available cumulative patch.

One of the following may provide a workaround with older patch levels until the system can be patched:

  • Merge lock and refresh using entityManager.refresh(e, LockModeType.READ);
  • Reverse the order of lock/refresh (i.e. peform refresh before lock)

Root Cause

This is a known defect (HHH-13492).

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Comments