1. 소개

이 예제에서는 JPASpring Data JPA 로 쿼리 결과 를 제한하는 방법을 배울 것 입니다.

먼저 쿼리하려는 테이블과 재현하려는 SQL 쿼리를 살펴보겠습니다.

그런 다음 JPA 및 Spring Data JPA를 사용하여 이를 달성하는 방법에 대해 자세히 알아보겠습니다.

시작하자!

2. 테스트 데이터

아래에는 이 기사 전체에서 쿼리할 테이블이 있습니다.

우리가 대답하고 싶은 질문은 "첫 번째 점유 좌석은 무엇이며 누가 점유하고 있습니까?"입니다.

이름 좌석 번호
처녀 스미스 50
이브 잭슨 94
프레드 블로그 22
리키 바비 36
시야 콜리시 85

3. SQL

SQL을 사용하면 다음과 같은 쿼리를 작성할 수 있습니다.

SELECT firstName, lastName, seatNumber FROM passengers ORDER BY seatNumber LIMIT 1;

4. JPA 설정

JPA를 사용하면 테이블을 매핑하기 위해 먼저 엔터티가 필요합니다.

@Entity
class Passenger {

    @Id
    @GeneratedValue
    @Column(nullable = false)
    private Long id;

    @Basic(optional = false)
    @Column(nullable = false)
    private String fistName;

    @Basic(optional = false)
    @Column(nullable = false)
    private String lastName;

    @Basic(optional = false)
    @Column(nullable = false)
    private int seatNumber;

    // constructor, getters etc.
}

다음으로 여기에서 PassengerRepositoryImpl#findOrderedBySeatNumberLimitedTo(int limit) 로 구현된 쿼리 코드를 캡슐화하는 메서드가 필요합니다 .

@Repository
class PassengerRepositoryImpl {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public List<Passenger> findOrderedBySeatNumberLimitedTo(int limit) {
        return entityManager.createQuery("SELECT p FROM Passenger p ORDER BY p.seatNumber",
          Passenger.class).setMaxResults(limit).getResultList();
    }
}

저장소 메서드에서 EntityManager 를 사용하여 setMaxResults() 메서드 를 호출  하는 쿼리 를 만듭니다 .

Query#setMaxResults 에 대한 이 호출 은 결과적으로 생성된 SQL에 추가된 제한 문이 생성됩니다.

select
  passenger0_.id as id1_15_,
  passenger0_.fist_name as fist_nam2_15_,
  passenger0_.last_name as last_nam3_15_,
  passenger0_.seat_number as seat_num4_15_
from passenger passenger0_ order by passenger0_.seat_number limit ?

5. 스프링 데이터 JPA 사용

Spring Data JPA를 사용하여 SQL을 생성할 수도 있습니다.

5.1. 첫 번째 또는  상단

이에 접근할 수 있는 한 가지 방법은 first 또는 top 키워드와 함께 메서드 이름 파생을 사용하는 것입니다.

선택적으로 반환될 최대 결과 크기로 숫자를 지정할 수 있습니다. 생략하면 Spring Data JPA는 결과 크기를 1로 가정합니다.

가장 먼저 차지한 자리와 누가 차지했는지 알고 싶기 때문에 다음 두 가지 방법으로 숫자를 생략할 수 있습니다.

Passenger findFirstByOrderBySeatNumberAsc();
Passenger findTopByOrderBySeatNumberAsc();

위와 같이 하나의 인스턴스 결과로 제한하면 Optional 을 사용하여 결과를 래핑할 수도 있습니다 .

Optional<Passenger> findFirstByOrderBySeatNumberAsc();
Optional<Passenger> findTopByOrderBySeatNumberAsc();

5.2. 페이징 가능

또는 Pageable 객체를 사용할 수 있습니다.

Page<Passenger> page = repository.findAll(
  PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "seatNumber")));

JpaRepository 의 기본 구현인  SimpleJpaRepository  를 살펴보면 Query  # setMaxResults 도 호출한다는 것을 알 수 있습니다 .

protected <S extends T > Page < S > readPage(TypedQuery < S > query, 
  Class < S > domainClass, Pageable pageable,
  @Nullable Specification < S > spec) {
    if (pageable.isPaged()) {
        query.setFirstResult((int) pageable.getOffset());
        query.setMaxResults(pageable.getPageSize());
    }

    return PageableExecutionUtils.getPage(query.getResultList(), pageable, () -> {
        return executeCountQuery(this.getCountQuery(spec, domainClass));
    });
}

5.3. 비교

이 두 가지 대안 모두 첫 번째  및  최상위 선호 규칙과  Pageable 선호 구성 으로 우리가 추구하는 SQL을 생성합니다  .

select
  passenger0_.id as id1_15_,
  passenger0_.fist_name as fist_nam2_15_,
  passenger0_.last_name as last_nam3_15_,
  passenger0_.seat_number as seat_num4_15_ 
from passenger passenger0_ order by passenger0_.seat_number asc limit ?

6. 결론

JPA 에서 쿼리 결과를 제한 하는 것은 SQL과 약간 다릅니다. 우리는 JPQL 에 limit 키워드를 직접 포함하지 않습니다 .

대신 Query#maxResults 에 대한 단일 메소드 호출을 수행하거나 Spring Data JPA 메소드 이름 에 키워드 first 또는 top 을 포함합니다.

항상 그렇듯이 코드는 GitHub 에서 사용할 수 있습니다 .

Persistence footer banner