Introduction
Locking is an essential way to avoid data inconsistancy when two sources try to update same data simultaneously. In the previous blog, we covered the optimistic locking, in which a lock is applied to avoid dirty reading.
In this blog, we'll cover the Pessimistic locking. Pessimistic Locking is useful when we need to lock the data before a transaction, so that it cannot be modified by any other transaction. This lock retains until the transaction commits or roll back.
There are three types of pessimistic lock mode:
PESSIMISTIC_READ: for shared lock, it prevents data deletion or updation
PESSIMISTIC_WRITE: for exclusive lock, it prevents read, delete or update the data
PESSIMISTIC_FORCE_INCREMENT: similar to PESSIMISTIC_WRITE including a version attribute
Setting a Pessimistic Lock
There are several ways to set up a pessimistic lock:
1. Find method of entityManager
Pass a parameter for LockModeType in find function.
entityManager.find(User.class, userId, LockModeType.PESSIMISTIC_READ);
2. setLockMode of query
you can use setLockMode function of Query to enable the lock.
Query query = entityManager.createQuery("from User where userId = :userId"); query.setParameter("userId", userId); query.setLockMode(LockModeType.PESSIMISTIC_WRITE); query.getResultList()
3. Refresh
Pass parameter of LockModeType in refresh, which a method of enitityManager.
User result = entityManager.find(User.class, userId); entityManager.refresh(result, LockModeType.PESSIMISTIC_FORCE_INCREMENT);
4. Explicit Locking
Another method, lock of enitityManager is available to directly apply lock on a particular enitiy.
User result = entityManager.find(User.class, userId); entityManager.lock(result, LockModeType.PESSIMISTIC_WRITE);
5. NamedQuery
You can also use Named query.
@NamedQuery(name="userLock", query="SELECT s FROM User s WHERE s.id LIKE :userId", lockMode = PESSIMISTIC_READ)