Our scenario:
- JPA entity gets loaded (via Hibernate) and passed to the front-end (including the version of the entity).
- The user modifies the data and then (possibly a couple of minutes later), the modified entity data is sent from the front-end (FE) to the back-end (BE) (including ID and the version of the entity).
- On the BE, the corresponding entity is again loaded from the DB, updated with new values coming from FE (including version) and saved to the DB.
Problem: Optimistic locking (concurrent modification detection) doesn't work because the version attribute is modified in such a way that concurrent modification cannot be detected.
For example, an entity has version 100 at the time it is first loaded from the DB. While the entity data is being modified by Alice on the FE (say, for 30 minutes), the entity is modified five times by some automatic process and its version gets increased to 105. When Alice finishes its changes, the application sends the modified data to the BE. The BE loads the corresponding entity (now in version 105) from the DB and updates its attributes with values that came from the FE, including the version attribute. So the managed entity has been loaded with version 105 but the version was later explicitly changed to 100. Now, the BE calls EntityManager.merge(…)
to save the data to the DB. Once the JPA flush is invoked, the version field gets increased and the data is saved to the DB.
The problem is that, during flush, the version is not increased to 101 (as I expect) but to 106.
Is this the correct behaviour? How can I make it work the intended way?
I have tested this with Hibernate 5.1.10 and 5.2.17.