When two transactions modify the same entity, the later update can overwrite an earlier one. Optimistic versioning detects this conflict without treating every read as a locked operation. It is suited to applications where concurrent modifications are rare and a conflict can be detected late in a unit of work. section 11.2.1 section 11.2.2
Add an `@Version` property to a JPA entity to enable automatic checking. Its value is a concurrency counter, not an application timestamp or a history of changes. The application should not set it. When Hibernate flushes a dirty entity, it increments the version and includes the previously loaded value in the update condition. If another transaction has changed the row, the check fails with an optimistic-lock exception: the first commit wins. section 11.2.2
Listing 11.2 Hibernate incrementing and checking the version automatically
Path: /Ch11/transactions/src/test/java/com/manning/javapersistence/ch11 /concurrency/Versioning.java – firstCommitWins() EntityManager em1 = emf.createEntityManager(); em1.getTransaction().begin(); Item item = em1.find(Item.class, ITEM_ID); #1 // select * from ITEM where ID = ? assertEquals(0, item.getVersion()); #2 item.setName("New Name"); // . . . Another transaction changes the record assertThrows(OptimisticLockException.class, () -> em1.flush()); #3 // update ITEM set NAME = ?, VERSION = 1 where ID = ? and VERSION = 0 #1 Retrieving an entity instance by identifier loads the current version from the database with a <kbd>SELECT</kbd>. #2 The current version of the <kbd>Item</kbd> instance is <kbd>0</kbd>. #3 When the persistence context is flushed, Hibernate detects the dirty <kbd>Item</kbd> instance and increments its version to <kbd>1</kbd>. SQL <kbd>UPDATE</kbd> now performs the version check, storing the new version in the database, but only if the database version is still <kbd>0</kbd>.
The test shows an entity loaded at version 0, a competing change, and an update conditioned on `VERSION = 0` that fails at flush time. section 11.2.2
Choose the check to match the work being protected:
- Use automatic `@Version` checking for concurrently modified entities. A numeric property is sufficient; a timestamp can also serve as the version value. section 11.2.2
- Request `LockModeType.OPTIMISTIC` when a read-only calculation must verify that the entities it read have not changed before completion. section 11.2.2
- Use `LockModeType.OPTIMISTIC_FORCE_INCREMENT` when the transaction needs to advance an entity’s version even without an ordinary dirty-entity update. section 11.2.2
Version checking complements, rather than replaces, a choice of database isolation level. Persistence-context caching and versioning both affect the behavior an application observes; choose isolation for the actual workload and its scalability requirements. section 11.2.1
A single `@Version` value detects conflicting changes but does not retain old entity states. For historical versions, Hibernate Envers copies selected changes into separate audit tables, groups modifications in a transaction under a revision number, and supports queries by revision or timestamp. That history costs additional tables. section 11.2.2 section 13.3
























