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