liveBook · Manning

Lock timeout

As explained in Java Persistence with Spring Data and Hibernate epub

A lock timeout is a configured duration after which a DBMS stops waiting to acquire an unavailable lock.

A lock timeout configures how long a database waits for an unavailable lock before stopping the query. JPA applies it with the javax.persistence.lock.timeout hint on queries or find operations. section 11.2.3

Account for these implementation and transaction differences:

  • Hibernate may ignore the hint when the database does not support query-specific timeouts; H2 instead uses a connection-wide default of one second. section 11.2.3
  • A zero timeout may generate NOWAIT on PostgreSQL and Oracle dialects. section 11.2.3
  • LockTimeoutException does not make the transaction fatal, whereas PessimisticLockException requires rollback and ends the unit of work. 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.

See a pessimistic-read query configured with a 5,000-millisecond timeout while another transaction competes for the lock. section 11.2.3

How Java Persistence with Spring Data and Hibernate epub covers it

How deep it goes
Explains JPA configuration, dialect translation, unsupported databases, and transaction-specific exception consequences.
Examples
Uses a 5,000-millisecond query hint, find operation, H2's one-second default, and PostgreSQL or Oracle NOWAIT behavior.
What it assumes
Assumes familiarity with EntityManager operations, transactions, pessimistic lock modes, and database-level locking.
What you can do after
Apply it via JPA and Hibernate, then handle timeout and pessimistic-lock exceptions according to transaction impact.
How it connects
Connects pessimistic locking, lock modes, database dialects, transactions, and entity versioning.

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.