1. 소개
이 예제에서는 JPA 및 Spring 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 에서 사용할 수 있습니다 .