Master Transaction Locks in Spring Data JPA: Pessimistic vs Optimistic
This tutorial explains how to enable and configure transaction locks—including pessimistic and optimistic modes—in Spring Data JPA repositories, demonstrates the use of @Lock and @QueryHints annotations, and shows how to set lock timeouts to ensure data integrity under high concurrency.
1. Overview
In this quick tutorial we discuss how to enable transaction locks for custom query methods and predefined repository methods in Spring Data JPA, covering lock types and lock timeout settings.
2. Lock Types
JPA defines two main lock types: pessimistic lock and optimistic lock.
2.1 Pessimistic Lock
When a pessimistic lock is used inside a transaction, the entity is locked immediately and released on commit or rollback.
2.2 Optimistic Lock
Optimistic lock does not lock the entity immediately; the transaction stores the entity state and assigns a version number. When updating, the stored version is compared with the current version, and if they differ an OptimisticLockException is thrown.
Other strategies such as timestamps, hash values, or checksums can also be used.
3. Enabling Transaction Lock on Query Methods
Use the @Lock annotation on the target query method and specify the desired LockModeType .
Example:
@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
@Query("SELECT c FROM Customer c WHERE c.orgId = ?1")
List<Customer> fetchCustomersByOrgId(Long orgId);To lock predefined repository methods (e.g., findAll or findById), declare the method and annotate it with @Lock:
@Lock(LockModeType.PESSIMISTIC_READ)
Optional<Customer> findById(Long customerId);If a lock is enabled without an active transaction, a TransactionRequiredException is thrown. If a lock cannot be granted and the conflict does not cause a rollback, JPA throws LockTimeoutException without marking the transaction for rollback.
4. Setting Transaction Lock Timeout
When a pessimistic lock cannot be obtained immediately, JPA throws LockTimeoutException. To avoid this, specify a lock timeout using @QueryHints:
@Lock(LockModeType.PESSIMISTIC_READ)
@QueryHints(@QueryHint(name = "javax.persistence.lock.timeout", value = "3000"))
Optional<Customer> findById(Long customerId);Refer to ObjectDB articles for more details on lock timeout scopes.
5. Conclusion
This tutorial covered the different transaction lock modes, how to enable them in Spring Data JPA, and how to configure lock timeouts. Applying the appropriate lock in the right place helps maintain data integrity under high concurrency. Use pessimistic locks for strict ACID compliance and optimistic locks when concurrent reads are acceptable.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
