liveBook · Manning

Versioning

As explained in Java Persistence with Spring Data and Hibernate epub

Entity versioning associates persistent data with a version value that changes when it is updated, enabling concurrent modifications to be detected.

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

How Java Persistence with Spring Data and Hibernate epub covers it

How deep it goes
Shows @Version mapping and flush-time SQL checking, then extends to manual checks, forced increments, timestamps, and Envers revisions.
Examples
Uses a versioned entity update that conflicts at flush time, a category-price calculation, and an Envers historical-data query.
What it assumes
Assumes basic JPA entity and transaction use while showing the @Version mapping needed to enable automatic checking.
What you can do after
Apply it via JPA @Version and optimistic lock modes to detect conflicting updates; use Hibernate Envers when historical revisions are required.
How it connects
Links optimistic locking to transaction isolation, persistence-context flushing, repeatable reads, and audit logging.

Also explained in

Compare how 25 books explain versioning →

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.