When we talk about java enterprise applications, it’s very important to handle concurrent operations to a database properly. So, we need to handle bulk transactions in a very effective and in a without error way.
Also, we need to ensure data consistency between updates and concurrent reads operations.
Java Persistence API provides us optimistic locking mechanism to achieve above scenarios. It ensures us that multiple updates made on the same data at the same time each other. Let's understand optimistic locking as below:
Understanding optimistic locking:
To use optimistic locking, we need to annotate @Version annotation on a property of entity class. So, each transaction that reads data holds the value of the version property.
Every transaction checks the version property before updating into the database.
OptimisticLockException is thrown if the value has changed in the meantime by another transaction. Otherwise, the transaction commits and increments a value version property.
Pessimistic Locking vs. Optimistic Locking:
JPA also gives us pessimistic locking. It’s another way for handling concurrent access for data.
Let's consider pessimistic locking and find out benefit from each type of locking. Every transaction checks the version property before updating into the database.
As explained above, OptimisticLockException is thrown if the value has changed in the meantime by another transaction. Otherwise, the transaction commits and increments a value version property.
This mechanism is suitable for applications which do much more reads then updates or deletes. It's also useful where entities must be detached for some time and locks cannot be held.
Pessimistic locking locks entities on the database level.
In pessimistic locking, deadlocks may occur because as long as it holds the lock, no transaction can read, delete or make any updates on the locked data. However, it ensures the great integrity of data than optimistic locking.
Version attributes come with @Version annotation and they are necessary to achieve optimistic locking. Let’s see an example:
Rules to declare version attributes:
- Only one version attribute is allowed on each entity class.
- If there are mapping in entities then it should be in the primary entity class.
- Type of version attribute areas listed below : Int, Integer, long, Long, short, Short, java.sql.Timestamp
If we do not use @Version annotation and try to lock an entity class and the persistence provider does not support it then we will see the result with exception called PersistenceException.
JPA provides different optimistic lock modes as described below:
- OPTIMISTIC- Those entities contains version attributes will obtains an optimistic read lock.
- OPTIMISTIC_FORCE_INCREMENT- It same as OPTIMISTIC except it additionally increments the version attribute value.
- READ- It’s a synonym for OPTIMISTIC_LOCK.
- WRITE- It’s a synonym for OPTIMISTIC_LOCK_INCREMENT.
We also can find above in LockModeType class.
Implementation Of Optimistic Locking:
By default versioned entities optimistic locking is available.
By passing LockModeType in arg we can explicitly use optimistic locking. For Eg:
Another way is to use setLockMode method:
- EXPLICIT LOCKING:
By using EntityManager’s lock method:
- NAMED QUERY:
Another option is to use @NamedQuery with the lockMode property:
In this blog, we got familiar with concurrent transaction, Optimistic locking uses version attributes and how to control concurrent modifications on them.
Therefore, it ensures that transactions won’t be overlap or overwritten or lost. We also saw the comparison in between pessimistic locking and optimistic locking and came to knew that optimistic locking doesn’t lock entities on the database level and consequently, it’s also not vulnerable to deadlocks.
Hope, This will help you to explore more.