Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a PessimisticLockException with JPA

I am trying JPA's support of database locking in order to avoid concurrent requests in a record. In my scenario I need to use a pesssimistic lock. I got that using the following approach:

EntityManager em;
...

Map<String,Object> props = new HashMap<String,Object>();
props.put("javax.persistence.lock.timeout", 0);
em.find(MyEntity.class, id, LockModeType.PESSIMISTIC_READ, props)

but with that approach I handle a LockTimeoutException instead of a PessimisticLockException. How to handle a PessimisticLockException specifically?

like image 874
Geison Santos Avatar asked Jul 25 '17 16:07

Geison Santos


People also ask

How do you do specific locking in Spring JPA?

To specify a lock on a custom query method of a Spring Data JPA repository, we can annotate the method with @Lock and specify the required lock mode type: @Lock(LockModeType. OPTIMISTIC_FORCE_INCREMENT) @Query("SELECT c FROM Customer c WHERE c.

How do you get pessimistic locking in hibernate?

Pessimistic locking in hibernatePessimisticLockException will be thrown when we query for rows which are already locked. If the initial select query is successful, rows which meet the select query criteria are locked for the duration of a transaction. We can be sure that no other transaction will modify them.

How do you implement optimistic locking in JPA?

In order to use optimistic locking, we need to have an entity including a property with @Version annotation. While using it, each transaction that reads data holds the value of the version property. Before the transaction wants to make an update, it checks the version property again.

How do you test for pessimistic locking?

Using the "test-oracle", "test-mysql" or "test-postgresql" profile for your integration tests will allow you to run all pessimistic locking handling tests against your production database. 🔔 This format is suitable for the local environment when you do changes to your pessimistic locking handling.


1 Answers

According to the spec, the PessimisticLockException only occurs on a transaction-level rollback:

When the lock cannot be obtained, and the database locking failure results in transaction-level rollback, the provider must throw the PessimisticLockException and ensure that the JTA transaction or EntityTransaction has been marked for rollback.

Your transaction seems to consists only of that single data retrieval query and the persistence provider considers that if a lock error occurs on that query, then the rollback would be considered as a statement-level rollback. Which according to the spec would result in the LockTimeoutException:

When the lock cannot be obtained, and the database locking failure results in only statement-level rollback, the provider must throw the LockTimeoutException (and must not mark the transaction for rollback).

I think thats a clever way of the driver / persistence provider to give you a chance to repeat / fix your statement instead of rolling back the whole transaction implicitly.

In general, I think that if you had an insert or an update before that find (or some more complex data manipulation statements), then you would get the PessimisticLockException.

like image 161
Maciej Kowalski Avatar answered Sep 29 '22 07:09

Maciej Kowalski