How to implement for update skip locked in Spring Data JPA
Asked Answered
G

0

1

I need to get 20 users from the postgres database (without sorting), do some actions with them, and then delete them as part of the transaction. If I were using a native sql query, I would write like this:

  SELECT 
        user_id,
        birthday,
        username 
  FROM users 
  WHERE
       username = $1 
  FOR UPDATE SKIP LOCKED limit 20;

But I need to make a query using Spring Data Jpa. To do this, I'm trying to use locks and limit. I am using Spring Boot 3.2.3 and PostgreSql.

@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;

    @Transactional
    public void getUsersByUsernameWithLock() {
        List<User> users = userRepository.findByUsername("user");
        System.out.println(users, Limit.of(20));
        //do something
        //delete
    }
}

public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByUsernameAndBirthday(String username, LocalDate birthday);

    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @QueryHints({@QueryHint(name = "jakarta.persistence.lock.timeout", value ="-2")})
    List<User> findByUsername(String username, Limit limit);
}

When I look at the query that spring jpa builds, I see that it adds for no key update and offset instead of limit:

Hibernate: 
    /* <criteria> */ select
        u1_0.user_id,
        u1_0.birthday,
        u1_0.username 
    from
        users u1_0 
    where
        u1_0.username=? 
    offset
        ? rows 
    fetch
        first ? rows only for no key update skip locked


org.hibernate.orm.jdbc.bind              : binding parameter (1:VARCHAR) <- [user]
org.hibernate.orm.jdbc.bind              : binding parameter (2:INTEGER) <- [0]
org.hibernate.orm.jdbc.bind              : binding parameter (3:INTEGER) <- [10]

If using offset and fetch instead of limit seems like a good practice, for no key update is not exactly what I would like. How do I tell JPA to generate a query with for update?

Gintz answered 3/3 at 17:23 Comment(1)
I'm actually surprised that you got "skip locked"... but In your situation I would have used a native query here. Spring Data JPA does have native query support, see for example thorben-janssen.com/native-queries-with-spring-data-jpa.Adventure

© 2022 - 2024 — McMap. All rights reserved.