PESSIMISTIC_READ is a JPA lock mode for repeatable reads during a database transaction. Hibernate translates it into dialect-specific database locking, such as FOR SHARE on PostgreSQL, LOCK IN SHARE MODE on MySQL, or FOR UPDATE on H2. section 11.2.3
Listing 11.6 Locking data pessimistically
Path: /Ch11/transactions/src/test/java/com/manning/javapersistence/ch11 /concurrency/Locking.java – pessimisticReadWrite() 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.PESSIMISTIC_READ) .setHint("javax.persistence.lock.timeout", 5000) .setParameter("catId", categoryId) .getResultList(); for (Item item : items) #2 totalPrice = totalPrice.add(item.getBuyNowPrice()); // . . . Another transaction tries to obtain a lock and fails } em.getTransaction().commit(); #3 em.close(); assertEquals(0, totalPrice.compareTo(new BigDecimal("108"))); #1 For each <kbd>Category</kbd>, query all <kbd>Item</kbd> instances in <kbd>PESSIMISTIC_READ</kbd> lock mode. Hibernate locks the rows in the database with the SQL query. If another transaction holds a conflicting lock, wait 5 seconds if possible. If the lock can’t be obtained, the query throws an exception. #2 If the query returns successfully, we know that we hold an exclusive lock on the data, and no other transaction can access it with an exclusive lock or modify it until this transaction commits. #3 The locks are released after committing, when the transaction completes.
A transaction loads items with PESSIMISTIC_READ, applies a five-second lock timeout, and aggregates prices while the locks remain held. section 11.2.3
Operational characteristics:
- Holds the lock for one database transaction and throws an exception when the database cannot obtain it. section 11.2.3
- Differs from PESSIMISTIC_WRITE, which additionally serializes data access and prevents phantom reads. section 11.2.3
- Differs from optimistic locking, which can detect conflicts at commit rather than when the locking query executes. section 11.2.3
