How to Use @Lock in Spring Boot to Solve Concurrency Issues

This article explains how Spring Boot 3.5.0 leverages the @Lock annotation and JPA LockModeType to apply pessimistic read or write locks, shows custom repository implementations, provides concrete code snippets and generated SQL, and emphasizes that all lock operations must run inside a transaction.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
How to Use @Lock in Spring Boot to Solve Concurrency Issues

1. Introduction

In high‑concurrency scenarios such as order‑status queries, inventory deduction, or sensitive data reads, read/write locks ensure data consistency. Spring Data JPA can apply declarative pessimistic locks via @Lock together with transaction management; the framework translates the lock mode to the appropriate FOR UPDATE or FOR SHARE clause.

JPA’s LockModeType enum provides:

LockModeType.PESSIMISTIC_READ – shared (read) lock.

LockModeType.PESSIMISTIC_WRITE – exclusive (write) lock.

If the underlying database does not support shared locks, PESSIMISTIC_READ falls back to PESSIMISTIC_WRITE.

2. Practical Cases

2.1 Direct entity locking

Use EntityManager.find with a lock mode:

private final EntityManager entityManager;

@Transactional
public Student queryById(Long id) {
    return entityManager.find(Student.class, id, LockModeType.PESSIMISTIC_READ);
}

Generated SQL (shared lock):

select s1_0.id, s1_0.name, s1_0.sno
from x_student s1_0
where s1_0.id=? for share

2.2 Custom repository exposing a generic lock method

Define a generic repository interface:

public interface CustomRepository<T, ID> {
    T lockById(Class<T> entityClass, ID id, LockModeType lockMode);
}

Implement the interface (implementation class name must end with Impl):

public class CustomRepositoryImpl<T, ID> implements CustomRepository<T, ID> {

    @PersistenceContext
    private EntityManager entityManager;

    @Transactional
    @Override
    public T lockById(Class<T> entityClass, ID id, LockModeType lockMode) {
        return entityManager.find(entityClass, id, lockMode);
    }
}

Extend the custom repository in a concrete repository:

public interface StudentRepository extends JpaRepository<Student, Long>,
                                            CustomRepository<Student, Long> {
}

Use the lock method in a service:

private final StudentRepository studentRepository;

@Transactional
public Student queryById(Long id) {
    return studentRepository.lockById(Student.class, id, LockModeType.PESSIMISTIC_READ);
}

The generated SQL is identical to the direct‑entity example, using for share.

2.3 Query‑level locking with @Lock

Annotate a repository method with @Lock to lock rows returned by a JPQL query:

public interface PostCommentRepository extends JpaRepository<PostComment, Long> {

    @Transactional
    @Query("""
        select pc
        from PostComment pc
        where pc.post.id = :postId
    """)
    @Lock(LockModeType.PESSIMISTIC_READ)
    List<PostComment> lockAllByPostId(@Param("postId") Long postId);
}

Generated SQL (shared lock):

select pc1_0.id, pc1_0.content, pc1_0.created_at, pc1_0.post_id
from post_comment pc1_0
where pc1_0.post_id=? for share

Override an existing method to apply an exclusive lock:

@Override
@Transactional
@Lock(LockModeType.PESSIMISTIC_WRITE)
Optional<PostComment> findById(Long id);

Generated SQL (exclusive lock):

select pc1_0.id, pc1_0.content, pc1_0.created_at, pc1_0.post_id
from post_comment pc1_0
where pc1_0.id=? for update

All lock‑related operations must be executed within a transactional context.

Environment: Spring Boot 3.5.0

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

transactionSpring Bootpessimistic-lockjpacustom-repositorylockmode
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.