OptimisticLockException after locking, refreshing, and updating an entity

Description

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

Environment

None

Activity

Show:
Gail Badner
July 24, 2019, 4:48 PM

The problem here is that an EntityVerifyVersionProcess is registered with the EntityEntry associated with the entity at the time that the entity is locked.

Later, when the entity is refreshed, that EntityEntry is replaced by a new one in the PersistenceContext. This makes the EntityEntry registered with the EntityVerifyVersionProcess stale.

After the updated entity is pushed to the database by EntityUpdateAction#execute, which calls EntityEntry#postUpdate to update the version in the entity and the current EntityEntry.

Later, when EntityVerifyVersionProcess#doBeforeTransactionCompletion executes using the stale EntityEntry, OptimisticLockException is thrown because the version in the stale EntityEntry does not match the current version.

Workarounds:

  • lock the entity when it is refreshed; i.e., entityManager.refresh(entity, LockModeType.READ);

  • refresh the entity first, then lock it.

Gail Badner
July 24, 2019, 9:42 PM

Fixed in master branch.

Gail Badner
July 30, 2019, 8:37 PM

Fixed in 5.3 branch as well.

Assignee

Gail Badner

Reporter

Stephen Fikes

Fix versions

Labels

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

Priority

Major
Configure