Pessimistic Locking in Spring Data JDBC

175 Views Asked by At

In my SeatDAO I declare a findAll method with derived query. The DAO looks like this:

public interface SeatDAO extends CrudRepository<SeatDTO, Integer> {

    @Lock(LockMode.PESSIMISTIC_READ)
    Collection<SeatDTO> findAll();

}

When I now start the spring boot application along the PostgreSQL database, it gives me these errors:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'seatDAO' defined in demo.adapters.database.SeatDAO defined in @EnableJdbcRepositories declared on JdbcRepositoriesRegistrar.EnableJdbcRepositoriesConfiguration: Could not create query for public abstract java.util.Collection demo.adapters.database.SeatDAO.findAll(); Reason: No property 'findAll' found for type 'SeatDTO'

Caused by: org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract java.util.Collection demo.adapters.database.SeatDAO.findAll(); Reason: No property 'findAll' found for type 'SeatDTO'

Caused by: org.springframework.data.mapping.PropertyReferenceException: No property 'findAll' found for type 'SeatDTO'

When I leave out pessimistic locking on findAll by dropping @Lock, the application runs without any problems.

What is the problem here and how can I solve this?

Thank you in advance.

2

There are 2 best solutions below

4
Rajesh Mishra On BEST ANSWER

The core issue lies in the @Lock(LockMode.PESSIMISTIC_READ) annotation being incorrectly applied to the findAll() method. Spring Data JPA's @Lock annotation is intended for locking individual entity instances, not for locking entire query results. The framework is attempting to interpret findAll() as a property of the SeatDTO entity, leading to the

"No property 'findAll' found" error.

Remove the @Lock annotation from the findAll() method:

public interface SeatDAO extends CrudRepository<SeatDTO, Integer> {

    Collection<SeatDTO> findAll();

}

Alternatives for Pessimistic Locking:

Lock individual entities within a transaction:

Java - Inside a transactional context

for (SeatDTO seat : seatDAO.findAll()) {
    // Lock each seat individually
     transactionManager.lock(seat, LockMode.PESSIMISTIC_READ);
    // Perform operations on the locked seat
}
0
Kobi On

The findAll method is used to load all aggregates from the database. In my case, it is not even optimal to lock this method, since it is not used to modify any aggregate. As Rajesh Mishra already stated, you usually lock single instances (irrespective of JPA or JDBC).

But if we really want lock all saved aggregates, we can lock the findBy methods pessimistically using @Lock(LockMode.PESSIMISTIC_WRITE), then load all aggregates via findAll in the service class and load all the aggregates by findBy. For this, you also need to annotate the according service method with @Transactional.