Automatic version checking detects conflicts when a versioned entity is updated or deleted. A read-only unit of work may also need to know whether the entities it used changed before completion. Manual version checking requests that check explicitly. section 11.2.2
Map a version property with `@Version`, then request `LockModeType.OPTIMISTIC` on the query that loads the entities. Hibernate checks their versions at flush or commit, even if the transaction never modifies them. This suits work that can detect a rare conflict late rather than prevent concurrent changes. section 11.2.2
Listing 11.4 Requesting a version check at flush time to ensure repeatable reads
Path: /Ch11/transactions/src/test/java/com/manning/javapersistence/ch11 /concurrency/Versioning.java – manualVersionChecking() EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); BigDecimal totalPrice = BigDecimal.ZERO; for (Long categoryId : CATEGORIES) { List<Item> items = #1 em.createQuery("select i from Item i where i.category.id = :catId", Item.class) .setLockMode(LockModeType.OPTIMISTIC) .setParameter("catId", categoryId) .getResultList(); for (Item item : items) totalPrice = totalPrice.add(item.getBuyNowPrice()); } em.getTransaction().commit(); #2 em.close(); assertEquals("108.00", totalPrice.toString()); #1 For each <kbd>Category</kbd>, query all <kbd>Item</kbd> instances with an <kbd>OPTIMISTIC</kbd> lock mode. Hibernate now knows it has to check each <kbd>Item</kbd> at flush time. #2 For each <kbd>Item</kbd> loaded earlier with the locking query, Hibernate executes a <kbd>SELECT</kbd> during flushing. It checks whether the database version of each <kbd>ITEM</kbd> row is still the same as when it was loaded. If any <kbd>ITEM</kbd> row has a different version or the row no longer exists, an <kbd>OptimisticLockException</kbd> is thrown.
The query requests an optimistic check while summing item prices across categories; committing completes the unit of work. section 11.2.2
When a related change must count as a conflict, `LockModeType.OPTIMISTIC_FORCE_INCREMENT` is a different choice: it requests a version increment even when the entity itself is not otherwise changed. section 11.2.2
