``` java
@Entity
public class Product {
@Id
private long id;
private String name;
private double price;
// constructors, getters and setters
}
```
2. Pagenation을 위한 Repository 만들기
```java
public interface ProductRepository extends PagingAndSortingRepository<Product, Integer> {
List<Product> findAllByPrice(double price, Pageable pageable);
}
```
- 페이지네시션을 위한 레포지토리 ProductRepository를 만들었다.
- 해당 레포지토리는 PagingAndSortingRepository이라는 레포지토리 인터페이스를 상속받고 있다.
- 때문에 해당 조상 인터페이스의 findAll(Pageable pageable)와 findAll(Sort sort)를 사용할 수 있게 되었다.
- 해당 인터페이스에는 이 2개 메서드만 선언되어 있다.
- 또한 PagingAndSortingRepository는 CrudRepository를 또 상속하고 있기에 CrudRepository의 메서드들을 사용할 수 있다.
- 현재 선언되어 있는 findAllByPrice 메서드는 이름에서 알 수 있듯이 가격을 조건으로 DB에서 데이터를 가져올 수 있는 기능의 메서드이다.
- PagingAndSortingRepository를 확장할 경우 이처럼 findAll()의 매개변수로 Sort와 Pageable을 함께 사용하여 가져올 데이터들을 필터링 할 수 있다.
3. 페이지네이션 구현하기
- 페이지네이션을 하려면 그전에 DB에서 우리는 데이터들을 가져와야 한다.(findAll(Pageable pageable))
- findAll(Sort sort)은 타입이 Iterable<T>이기 때문이다.
- Page<T> findAll(Pageable pageable);
※ Pageable 인터페이스에 대해서는 따로 정리할 예정.
- 이를 위해선 매개변수로 들어갈 Pageble 타입의 객체를 만들어야 한다.
- Pageble의 객체 생성에는 Pageable ofSize(int pageSize)이 사용된다.
- 더 정확히 말하자면 ofSize의 리턴값이 PageRequest.of(0, pageSize)인데 이 PageRequest는 Pageable(인터페이스)-AbstractPageRequest(추상클래스)-PageRequest(클래스)로 상속관계가 연결된 구조이다. 즉 Pageble을 구현한 것이 PageRequest.
- 어떤 메소드를 사용할지 알았으니 객체를 생성해보자
```java
Pageable firstPageWithTwoElements = PageRequest.of(0, 2);
Pageable secondPageWithFiveElements = PageRequest.of(1, 5);
```
- 첫번째는 데이터를 2개씩 나누고 그 중 첫 페이지의 값들 가져오라는 요청(PageRequest) 객체
- 두번째는 데이터를 5개씩 나누고 그 중 두번째 페이의 값들을 가져오라는 요청(PageRequest) 객체이다.
- 요청을 전달할 객체를 매개변수로 하여 우리가 원하는 DB의 데이터들을 가져오자.
```java
Page<Product> allProducts = productRepository.findAll(firstPageWithTwoElements);
List<Product> allTenDollarProducts =
productRepository.findAllByPrice(10, secondPageWithFiveElements);
```
- findAll()의 기본 리턴타입은 Page<T>이다. 원한다면 사용자가 Page<T>, a Slice<T>, or a List<T> 중에서 원하는 타입으로 커스텀해 paginated data를 가져올 수도 있다.
- 차이를 간단히만 설명하면 Page<T> 객체 생성시 DB의 값을 전부 확인하는 작업을 거치기에 전체를 count하는 기능이 들어간다. 만약 이러한 기능을 소모하고 싶지 않다면(Overhead cost) Slice<T> or a List<T>를 사용하면 된다.
- 첫줄은 findAll을 통해 모든 DB값을 확인하고 그중 페이징 조건(firstPageWithTwoElements)에 해당하는 값들을 Page<Product>으로 담았다.
- 다음 줄은 페이징 조건 + 가격(10)이라는 조건을 추가로 주어 원하는 값을 가져왔고 이를 List<Product> 타입으로 담아왔다.(Sort sort, Pageble pagable)
- 이로서 DB와의 통신이 마무리 되었다.
4. 페이지네이션과 Sorting
- 위의 내용에서 조금 확장 하여 findAll와 같은 메서드의 매개변수 값에 추가로 조건을 넣어 정렬기능을 넣은 값들을 가져올 수도 있다.
- 예를 들어 최신순으로 게시글을 정렬하면 20-19-18 역순으로 데이터들을 클라이언트에게 보여주어야 하지만 실제 DB의 게시판(테이블)의 게시글들은 오름차순일 것이다. 즉 데이터들을 요청할 때 아예 오름차순으로 달라고 하자는 것.
```java
Page<Product> allProductsSortedByName = productRepository.findAll(Sort.by("name"));
```
- 단순하게 어떤 조건(필터링)없이 값을 다 가져오고자 한다면 productRepository의 findAll의 매개변수로 정렬 조건(Sort.by("name"))만 넣어주면 된다.
- 만약 정렬 조건 + 페이징조건을 함께 적용한다면 이를 포함한 요청객체를 만들어주면 된다.
```java
Pageable sortedByName =
PageRequest.of(0, 3, Sort.by("name"));
Pageable sortedByPriceDesc =
PageRequest.of(0, 3, Sort.by("price").descending());
Pageable sortedByPriceDescNameAsc =
PageRequest.of(0, 5, Sort.by("price").descending().and(Sort.by("name")));
```
- PageRequest.of의 3번째 매개변수로 정렬 조건을 넣을 수 있다.
- .descending()를 통해 내림차순으로 데이터를 요청할 수 있다.
- 또한 마지막 처럼 여러개의 정렬 조건을 적용할 수도 있다.(가격과 이름으로 정렬)
댓글남기기