Use @Version when concurrent transactions may modify the same JPA entity. The annotation enables optimistic version checking: a conflicting change is detected when the entity is flushed, so the first committed change wins. section 11.2.2
Add a version property to the entity and map it to a database column. Hibernate manages its value; application code should not set it. section 11.2.2
When a changed entity is flushed, Hibernate increments its version and includes the previously loaded version in the UPDATE condition. If another transaction has changed the row, the condition no longer matches and the flush raises an OptimisticLockException. The number is a concurrency counter, not an application value. 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 example shows a loaded version of 0 and an UPDATE that succeeds only while the database row still has version 0. section 11.2.2
