liveBook · Manning

@Version

As explained in Java Persistence with Spring Data and Hibernate epub

@Version is the JPA annotation that identifies an entity property used for optimistic concurrency version checking.

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

Listing 11.1 Enabling versioning on a mapped entity
Path: Ch11/transactions/src/main/java/com/manning/javapersistence/ch11
 /concurrency/Item.java
 
@Entity
public class Item {
    @Version
    private long version;
    //  . . .
}

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

How Java Persistence with Spring Data and Hibernate epub covers it

How deep it goes
Traces the mapped version property through flushing, conditional SQL updates, and a failed concurrent update.
Examples
Shows an Item entity with a numeric version and a competing update that produces an OptimisticLockException.
What you can do after
Apply it via JPA @Version to detect conflicting entity changes without setting the version in application code.
How it connects
Connects @Version to optimistic concurrency control, persistence-context flushing, SQL UPDATE conditions, and optimistic lock modes.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Java Persistence with Spring Data and Hibernate epub. The section links point to the parts of the book it draws on.