Book Study/스프링 부트 핵심 가이드
08. Spring Data JPA 활용 (2)
정진킴
2023. 11. 7. 19:28
8.4 정렬과 페이징 처리
8.4.1 정렬 처리하기
- 일반적인 쿼리문에서 정렬을 사용할 때는 ORDER BY 구문을 사용한다.
- 기본 쿼리 메서드를 작성한 후 OrderBy 키워드를 삽입하고 정렬하고자 하는 컬럼과 오름차순/내림차순을 설정하면 정렬을 수행한다.
// Asc : 오름차순, Desc : 내림차순
List<Product> findByNameOrderByNumberAsc(String name);
List<Product> findByNameOrderByNumberDesc(String name);
-- DESC 쿼리
select
product0_.number as number1_0_,
product0_.created_at as created_2_0_,
product0_.name as name3_0_,
product0_.price as price4_0_,
product0_.stock as stock5_0_,
product0_.updated_at as updated_6_0_
from
product product0_
where
product0_.name=?
order by
product0_.number desc
- 여러 개 컬럼을 사용하는 정렬 구문 경우 And 또는 Or 를 사용하지 않고 우선순위를 기준으로 작성한다.
// And를 붙히지 않음
List<Product> findByNameOrderByPriceAscStockDesc(String name);
- 쿼리 메서드 뿐만 아니라 매개변수를 활용하여 쿼리를 작성할 수 있다.
// productRepository
List<Product> findByName(String name, Sort sort);
// service
productRepository.findByName("펜", Sort.by(Order.asc("price")));
productRepository.findByName("펜", Sort.by(Order.asc("price"), Order.desc("stock")));
// sort 가 많은 경우 메서드로 분리하여 호출 가능
productRepository.findByName("펜", getSort());
private Sort getSort() {
return Sort.by(
Order.asc("price"),
Order.desc("stock")
);
}
8.4.2 페이징 처리
- JPA 에서는 이 같이 페이징 처리를 위해 Page와 Pageable을 사용한다.
- 아래 소스는 Page 처리를 위한 쿼리 메서드 예시이다.
Page<Product> findByName(String name, Pageable pageable);
- 메서드를 호출할 때 리턴 타입으로 Page 객체를 받아야 하기 때문에 Page<Product>로 타입을 선언해서 리턴을 받는다.
- Pageable 파라미터를 전달하기 위해 PageRequest 클래스를 사용
- PageRequest는 Pageable 구현체이다.
Page<Product> productPage = productRepository.findByName("펜", PageRequest.of(0,2));
of 메서드 | 매개변수 설명 | 비고 |
of(int page, int size) | 페이지 번호(0부터 시작), 페이지당 데이터 개수 페이지 번호가 1이면 쿼리에 offset 이 들어감 |
데이터를 정렬하지 않음 |
of(int page, int size, Sort) | 페이지 번호, 페이지당 데이터 개수, 정렬 | sort에 의해 정렬 |
of(int page, int size, Direction, String... properties) | 페이지 번호, 페이지당 데이터 개수, 정렬 방향, 속성(컬럼) | Sort.by(direction, properties)에 의해 정렬 |
- 각 페이지를 구성하는 세부적인 값을 보려면 getContent() 를 호출 후 출력하면 배열 형태로 값이 출력된다.
Page<Product> productPage = productRepository.findByName("펜", PageRequest.of(0,2));
System.out.println(productPage.getContent());
8.5 @Query 어노테이션 사용하기
- 쿼리 메서드를 생성 할 수도 있지만 @Query 어노테이션을 사용해 직접 JPQL을 작성할 수도 있다.
- 만약 데이터베이스를 다른 데이터베이스로 변경할 일이 없다면 직접 해당 데이터베이스에 특화된 SQL을 작성할 수 있으며, 주로 튜닝된 쿼리를 사용하고자 할 때 직접 SQL을 작성한다.
@Query("SELECT p FROM Product p WHERE p.name = ?1")
List<Product> findByName(String name);
- ?1 은 첫번째 파라미터를 의미한다. 하지만 이 같은 방식을 사용할 경우 파라미터의 순서가 바뀌면 오류가 발생할 가능성이 있기 때문에 @Param 어노테이션을 사용하는 것을 추천한다.
@Query("SELECT p FROM Product p WHERE p.name = :name")
List<Product> findByNameParam(@Param("name") String name);
- @Query를 사용하면 엔티티 타입이 아닌 원하는 컬럼의 값만 추출할 수 있다.
- 메서드에서는 Object 배열의 리스트 형태로 리턴 타입을 지정해야 한다.
@Query<"SELECT p.name, p.stock FROM Product p WHERE p.name = :name")
List<Object[]> findByNameParam2(@Param("name") String name);