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
