A race condition can arise when accepting an auction bid. The application reads the highest bid, checks that a new bid is higher, then stores it. Another transaction may place a bid between the read and the insert, leaving the comparison based on stale data. section 11.2.2
Versioning the Item alone does not detect this conflict: inserting a separate Bid does not modify the Item. Use JPA’s OPTIMISTIC_FORCE_INCREMENT lock mode on the Item when reading it. The forced version change makes a concurrent conflict detectable at commit. If bids instead belong to an Item @ElementCollection, adding one increments the Item version without a forced increment. section 11.2.2
Listing 11.5 Forcing a version increment of an entity instance
Path: /Ch11/transactions/src/test/java/com/manning/javapersistence/ch11 /concurrency/Versioning.java – forceIncrement() EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Item item = em.find( #1 Item.class, ITEM_ID, LockModeType.OPTIMISTIC_FORCE_INCREMENT ); Bid highestBid = queryHighestBid(em, item); // . . . Another transaction changes the record Bid newBid = new Bid( new BigDecimal("45.45"), item, highestBid); em.persist(newBid); #2 assertThrows(RollbackException.class, () -> em.getTransaction().commit()); #3 em.close(); #1 <kbd>find()</kbd> accepts a <kbd>LockModeType</kbd>. The <kbd>OPTIMISTIC_FORCE_INCREMENT</kbd> mode tells Hibernate that the version of the retrieved <kbd>Item</kbd> should be incremented after loading, even if it’s never modified in the unit of work. #2 The code persists a new <kbd>Bid</kbd> instance; this doesn’t affect any values of the <kbd>Item</kbd> instance. A new row is inserted into the <kbd>BID</kbd> table. Hibernate wouldn’t detect concurrently made bids without a forced version increment of the <kbd>Item</kbd>. #3 When flushing the persistence context, Hibernate executes an <kbd>INSERT</kbd> for the new <kbd>Bid</kbd> and forces an <kbd>UPDATE</kbd> of the <kbd>Item</kbd> with a version check. If someone modified the <kbd>Item</kbd> concurrently or placed a <kbd>Bid</kbd> concurrently with this procedure, Hibernate throws an exception.
The transaction loads an Item with OPTIMISTIC_FORCE_INCREMENT, reads its highest bid, persists a new Bid, and demonstrates a failed commit after another transaction changes the record. section 11.2.2



















