기본 쿼리 메서드인 이름
을 통한 정렬과 페이징 처리도 가능하지만 다른 방법도 많이 쓰임
일반적인 쿼리문에 정렬을 할 때는 ORDER BY
구문을 사용
// ASC : 오름차순, Desc : 내림차순
List<Product> findByNameOrderByNumberAsc(String name);
List<Product> findByNameOrderByNumberDesc(String name);
상품정보를 이름으로 검색한 후 상품 번호로 오름,내림차순 정렬을 수행한다는 뜻
정렬에서는 And나 Or 키워드를 사용하지 않고 우선순위를 기준으로 차례대로 작성
// And를 붙이지 않음
List<Product> findByNameOrderByPriceAscStockDesc(String name);
이런 쿼리 메서드의 경우 이름이 길 경우 가독성이 떨어짐
-> 매개변수를 활용해 정렬할 수도 있음
밑의 부분을 Test가 아닌 ProductRepository 인터페이스에 넣어야 함
List<Product> findByName(String name, Sort sort);
이때는 이름을 키워드로 넣지 않고 Sort 객체를 활용해 매개변수로 받아들인 정렬 기준을 가지고 쿼리문을 자동작성하게 됨
@SpringBootTest
public class ProductRepositoryTest {
@Autowired
ProductRepository productRepository;
@Test
void sortingAndPagingTest(){
Product product1 = new Product();
product1.setName("펜");
product1.setPrice(1000);
product1.setStock(100);
product1.setCreatedAt(LocalDateTime.now());
product1.setUpdatedAt(LocalDateTime.now());
Product product2 = new Product();
product2.setName("펜");
product2.setPrice(5000);
product2.setStock(300);
product2.setCreatedAt(LocalDateTime.now());
product2.setUpdatedAt(LocalDateTime.now());
Product product3 = new Product();
product3.setName("펜");
product3.setPrice(500);
product3.setStock(50);
product3.setCreatedAt(LocalDateTime.now());
product3.setUpdatedAt(LocalDateTime.now());
Product savedProduct1 = productRepository.save(product1);
Product savedProduct2 = productRepository.save(product2);
Product savedProduct3 = productRepository.save(product3);
productRepository.findByName("펜", Sort.by(Order.asc("price")));
productRepository.findByName("펜", Sort.by(Order.asc("price"), Sort.Order.desc("stock")));
}
}
밑의 2줄 코드를 통해 메서드에 전달함
Hibernate:
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_.price asc
Hibernate:
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_.price asc,
product0_.stock desc
매개변수를 활용한 쿼리 메서드 사용 시 쿼리 메서드를 정의하는 단계에서 코드가 줄어들지만 호출하는 위치에서는 여전히 정렬 기준이 길어져 가독성이 어렵다
Sort 부분을 하나의 메서드로 분리해서 쿼리 메서드를 호출하는 코드를 작성하기도 함
private Sort getSort(){
return Sort.by{
Order.asc("price")
Order.desc("stock")
};
}
페이징이란 데이터베이스의 레코드를 개수로 나눠 페이지를 구분하는 것
ex) 25개의 레코드가 있다면 레코드를 7개씩, 총 4개의 페이지를 구분하고 그중에서 특정 페이지를 가져오는 것
JPA에서는 페이징 처리를 위해 Page와 Pageable을 사용
productRepository
Page<Product> findByName(String name, Pageable pageable);
리턴 타입으로 Page
를 설정하고, 매개변수에는 Pageable
타입의 객체를 의미
test/productRepositoryTest
Page<Product> productPage = productRepository.findByName("펜", PageRequest.of(0,2));
Pageable 파라미터를 전달 하기 위해 PageRequest
(Pageable 구현체) 사용
PageRequest는 of
메서드를 통해 PageRequest 객체 생성 -> 다양한 형태로 오버로딩 되었음
of(int page, int size)
of(int page, int size, Sort)
of(int page, int size, Direction, String properties)
위 코드 실행 결과
Hibernate:
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=? limit ?
Hibernate:
select
count(product0_.number) as col_0_0_
from
product product0_
where
product0_.name=?
select 쿼리에 limit 쿼리가 포함되어있음
만약 페이지번호를 0 아닌 1이상의 숫자로 설정하면 offset 키워드도 포함되어 레코드 목록을 구분해서 가져옴
페이지 객체 그냥 출력시
-> 값을 보여주지 않고 몇 번째 페이지에 해당하는지 확인 가능
System.out.println(productPage);
Page 1 of 2 containing com.springboot.advanced_jpa.data.entity.Product instances
getContent() 메서드를 활용하면 배열 형태로 값이 출력
System.out.pirntln(productPage.getContent());