In this article we are going to understand How can we handles concurrent updates in Hibernate. let understand first Concurrent Updates.
Concurrent Update happens when multiple user or threads attempt to update same data simultaneously. This situation leads to conflicts and If these conflicts not handled properly it result into data inconsistency. Inconsistent data can lead to incorrect result.
Here conflicts arise when multiple user or threads attempt to update or modify same data and data inconsistency occurs when data stored in DB violates data integrity rules.
In Hibernate, there are two ways to handle concurrent updates.
- Optimistic Locking
- Pessimistic Locking
Optimistic Locking
It works on the assumption that chances of conflicts between concurrent updates is less and hence it will allow concurrent access on data without acquiring any Lock on that data.
Let see how it works and its implementation.
- Optimistic Locking use a version or timestamp field to track changes and detect conflict. So , here Entity in hibernate must have a field version or timestamp. If this field is version then its type must be any numeric type like int, long, etc. And if it's timestamp then its type must be java.sql.Timestamp or java.time.LocalDateTime.
- This field must annotated with @Version or we must name it as version using column annotation like @Column(name="version")
- When entity fetched initially from DB, Hibernate stored this version field value.
- When an update operation happens , Hibernate compares this filed value with latest value of same filed in DB.
- If different it means some transaction already modified data and it detect the conflict. Once it detect the conflict it throws OptimisticLockException and now it's developer responsibility to handle this exceptions properly. Some of the common strategies to handle this exception is notify user about conflict and ask user to retry.
- Else it update the data into DB.
When should we use optimistic Locking?
It is suitable where the chances of conflict is less and application handle these conflicts efficiently whenever optimistic locking detect it. Here optimistic locking not resolve conflict it just detect and throws OptimisticLockException , so its application developer responsibility to resolve conflict in case of OptimisticLockException.
Some Examples are:
- If application performs read operation more than write operation, in such case optimistic locking is good choice as user can perform read operation without Locking data that they are reading and hence it improves system performance.
- If chances of conflicts to occur are rare. For example user is updating his/her personal details, user withdraw/Credit money on their bank account.
Pessimistic Locking
It assumes that chances of happening conflict is very high, therefore whenever a transaction access data, it acquires a lock on that data, this way it prevents other transactions from modifying it until the lock is released.
Hibernate provides various locking mode to acquire pessimistic lock, below are their detail
- LockMode.WRITE : To acquire an exclusive (write) lock on an entity or a group of entities.
- LockMode.READ : To acquire a shared (read) lock on an entity or a group of entities. Here its shared lock because Read locks do not block other read locks but prevents write locks from being acquired by other transactions.
- LockMode.NONE : It indicates no locking should be applied when accessing an entity or a group of entities
How to use these LockMode ?
To use these modes Hibernate provide various method as mentioned below:-
Session.load() : This method used to load an entity using its identifier. It return the proxy of entity object, means it don't hit database directly to load entity until and unless this entity is used.
Here while load an entity we can pass lock mode , like thissession.load(Entity.class, entityId, LockMode.PESSIMISTIC_WRITE)
By loading the entity with a pessimistic lock, Hibernate will acquire the lock on the entity in the database, this way it ensures that other transactions cannot acquire write locks on the same entity until the acquired lock is released.
-
Session.lock() : It used to acquire lock on an entity in database. This lock exists till transaction completes either by commit or rollback.
Example :
-
Query.setLockMode() : It is used to acquire lock on entities that are part of a query execution.
Example :
The specified lock mode will be applied during the execution of the query. Result of this query can fetch using methods query.getResultList() or query.uniqueResult().
When should we use pesimistic Locking?
- It should use in scenarios where frequency of conflicts is high and data integrity is critical. It ensures that only one transaction can modify the data at a time, preventing concurrent modifications that could lead to conflicts and inconsistencies.
- It also useful in scenarios where single transaction takes time for execution and involve multiple operation. pessimistic locking can help maintain consistency throughout the transaction.
Example :
- When booking a seat or making a reservation, you want to prevent multiple users from booking the same seat simultaneously.
Comments
Post a Comment