It seems that hibernate returns a cached entity instance from its L1 cache as a result of select with PESSIMISTIC_WRITE lock.
Let’s imagine that we have a human with age 18 in the database and two following concurrent transactions are executed:
| * TRANSACTION:1 | TRANSACTION:2 | * BEGIN | | * repository.findById(1) | BEGIN | * | human = repository.findById(1) // human.hashCode() == 22, age is 18 | * human = repository.findByIdLocked(1) | | * | human = repository.findByIdLocked(1) // SELECT FOR UPDATE Query is executed | * human.setAge(21) | blocked | * COMMIT | blocked | | // lock is released on DB, query returns row where age is 21, hibernate returns cached human instance obtained on first select | | human.hashCode() == 22 // true | | human.getAge() == 18 // true | | human.getAge() == 21 // false ↓ time
Is it supposed to be like this? Won’t it make sense to refresh the data in a cached version of entity as the DB call is executed in any case to acquire lock?
Sample project: GitHub - antalos/hibernate-test