Placing a bid requires reading the highest bid, comparing it with a new bid, and storing the new bid if it is higher. Another transaction can place a bid between the read and the insert. Ordinary versioning of the Item does not reveal this race because placing a Bid does not modify the Item. section 11.2.2
Use `LockModeType.OPTIMISTIC_FORCE_INCREMENT` when loading the Item to force its version forward. Concurrent bidding transactions can then conflict even though they insert separate Bid entities. This is useful when changes to related data should advance the version of an aggregate root. It is unnecessary if bids are an `@ElementCollection` of Item: adding to that collection already increments the Item version. 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 Item with the force-increment lock mode, reads the highest bid, and persists a new bid. A concurrent change makes the illustrated commit fail with a rollback exception. section 11.2.2
