liveBook · Manning

PESSIMISTIC_READ

As explained in Java Persistence with Spring Data and Hibernate epub

PESSIMISTIC_READ is a JPA lock mode that acquires a lock guaranteeing repeatable reads without necessarily preventing all concurrent reads.

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

How Java Persistence with Spring Data and Hibernate epub covers it

How deep it goes
Explains guarantees, transaction duration, timeout behavior, provider responsibility, and dialect-specific SQL, but not offline lock implementations.
Examples
Uses category-item price aggregation, lock timeouts, and PostgreSQL, MySQL, and H2 SQL translations.
What it assumes
Assumes familiarity with JPA queries, transactions, lock modes, and database locking terminology.
What you can do after
Operate/configure JPA queries with PESSIMISTIC_READ and a lock timeout, then assess dialect and transaction implications.
How it connects
Connects JPA lock modes with Hibernate, database transactions, optimistic locking, PESSIMISTIC_WRITE, and SQL dialects.

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.