liveBook · Manning

Automatic version checking

As explained in Java Persistence with Spring Data and Hibernate epub

Automatic version checking, or automatic versioning, tracks entity versions and compares the previously read version with the database version during updates or deletions to detect concurrent modification.

Automatic version checking detects competing changes to a JPA entity without locking it throughout a unit of work. It suits multiuser applications where concurrent modifications are uncommon and a conflict can be detected when changes are flushed. section 11.2.2

Add a numeric `@Version` property to the entity. It maps to a database column; the application should not set its value. When Hibernate flushes a dirty entity, it increments the version and includes the previously read version in the `UPDATE` condition. For example, an entity read at version 0 produces an update shaped like `UPDATE ITEM SET NAME = ?, VERSION = 1 WHERE ID = ? AND VERSION = 0`. If another transaction has changed the row, the flush raises an `OptimisticLockException` rather than silently overwriting that change. 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>.

Follow the entity load, intervening change, and failed flush alongside the version condition in the generated SQL. section 11.2.2

Choose the check that matches the unit of work:

  • For ordinary entity changes, `@Version` supplies the automatic check. A `LocalDateTime` version property is also shown as a timestamp-based mapping. section 11.2.2
  • For reads that must be checked even without an entity update, request `LockModeType.OPTIMISTIC` on the query. section 11.2.2
  • When an operation such as persisting a related `Bid` must change an `Item` version, request `LockModeType.OPTIMISTIC_FORCE_INCREMENT`. section 11.2.2

Hibernate also shows a versionless alternative using its `OptimisticLocking` and `DynamicUpdate` annotations: an update compares previously read column values in its `WHERE` clause. That approach is Hibernate-specific, unlike the basic JPA `@Version` mapping. section 11.2.2

How Java Persistence with Spring Data and Hibernate epub covers it

How deep it goes
Shows the entity mapping, generated update condition, failed flush, and explicit lock modes.
Examples
Uses a versioned `Item` update, a query that requests a read check, and a `Bid` operation that forces an increment.
What it assumes
Assumes familiarity with JPA entities and transactions while showing how to enable versioning.
What you can do after
Apply it via JPA `@Version` to detect competing writes and select explicit optimistic lock modes when automatic checks are insufficient.
How it connects
Connects optimistic concurrency control with persistence-context flushing, transaction isolation, and explicit optimistic locking.

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.