1. 오늘 겪은 에러
1)page redirect 시에는 GetMapping 을 써줘야한다. @PostMapping 의 경우 원하는 페이지로 갈 수 없다.
@GetMapping("/detail/buybooks/{bookid}/{quantity}")
public String Buybook(@PathVariable Long bookid, @PathVariable Long quantity) {
bookService.bookOrder(bookid, quantity);
String ans = bookid + "번 책을 " + quantity + " 권 주문한다용";
System.out.println(ans);
return "redirect:/main";
}
2. 페이지네이션
- 사용자가 요청했을 때 수천,수만,수백만 줄의 데이터를 모두 조회하여 제공하는 건 서버의 부하가 매우 크다.
- 이를 방지하기 위해 일정 길이로 잘라 일부만 제공한다.
1)Spring Data JPA가 제공하는 페이지네이션
- JPA로 페이지네이션 기능을 구현할 때 전체 데이터 개수를 가져와 전체 페이지를 계산하고, 현재 페이지가 몇번째 페이지 인지, 예상치 못한 범위를 요청받았을 때 예외처리도 해야해서 번거롭고 불편하다.
- 하지만 Spring Data JPA는 이런 페이지 네이션도 추상화 되어있어 페이지 크기와 순서만 전달하면 DB에서 해당 페이지에 해당하는 데이터만 가져올 수 있다.
2)Pageable과 PageRequest
- Pageable 과 PageRequest는 Spring data에서 제공하는 페이지네이션 정보를 담기위한 인터페이스와 구현체 이다.
3)PageRequest 생성
PageRequest page = PageRequest.of(0, 10);
- (페이지 순서, 페이지의 크기)이다. 페이지 순서는 0부터 시작이다.
4)Pageable의 ofSize() 스태틱 메소드
Pageable.ofSize(10);
- 페이지 번호를 0으로 고정하여 페이지 사이즈만 설정한다.
5)조회 결과 정렬
PageRequest.of(0, 10, Sort.by("price").descending());
PageRequest.of(0, 10, Sort.by(Direction.DESC, "price"));
PageRequest.of(0, 10, Sort.by(Order.desc("price")));
PageRequest.of(0, 10, Direction.DESC, "price");
- sort 클래스 혹은 sort의 내부 enum 클래스인 Direction을 사용하여 정렬을 설정 할 수 도있다.
- 여기서 "price"가 정렬 기준이 되는 칼럼 이름이다.
- 위 코드는 모두 내림차순으로 정렬된 것이다.
6)Slice와 Page
- Spring Data JPA 레포지토리에 Pageable을 전달하면, 반환 타입으로 Slice 혹은 Page를 받을 수 있다.
- 두 인터페이스 모두 조회 결과를 저장하는 역할을 한다
- Page는 Slice를 상속받는다.
7)Slice
- 전체 페이지 개수를 알아내기 위해서는 count 쿼리가 필요하지만 Slice는 별도로 실행하지 않는다.
- 무한 스크롤 구현 시 그저 다음 페이지 유무만 확인 하는 용도에 적합하다.
- 예를들어 페이지당 갯수가 10개일 때 11개를 불러와서 11개째가 있으면 다음 페이지가 있다는 것을 활용한다.
8)page
- Slice와 다르게 count 쿼리를 실행하여, 전체 데이터와 페이지 개수를 계산할 수 있다.
9)Silce와 Page 사용
- 사용전 공통 코드
@ToString
@NoArgsConstructor
@Getter
@Entity
public class Item {
@Id
@GeneratedValue
private Long id;
private String name;
private int price;
public Item(final String name, final int price) {
this.name = name;
this.price = price;
}
}
- Slice의 사용 코드
public interface ItemRepository extends JpaRepository<Item, Long> {
Slice<Item> findSliceByPrice(int price, Pageable pageable);
}
for (int i = 1; i <= 40; i++) {
itemRepository.save(new Item("상품" + i, 5000));
}
Slice<Item> itemSlice = itemRepository.findSliceByPrice(5000, PageRequest.of(0, 5));
for (Item item : itemSlice.getContent()) {
System.out.println(item.getName());
}
//실행결과
상품1
상품2
상품3
상품4
상품5
- Page 사용 코드
public interface ItemRepository extends JpaRepository<Item, Long> {
// ...
Page<Item> findPageByPrice(int price, Pageable pageable);
}
for (int i = 1; i <= 40; i++) {
itemRepository.save(new Item("상품" + i, 5000));
}
Page<Item> itemPage = itemRepository.findPageByPrice(5000, PageRequest.of(0, 5));
for (Item item : itemPage.getContent()) {
System.out.println(item.getName());
}
//실행결과
상품1
상품2
상품3
상품4
상품5
3. ElasticSearch
1)ElasticSearch와 관계형 데이터베이스의 차이
- RDB와 다르게 ES에서는 키워드에 대한 위치를 미리 알고있어 빠르게 서치가 가능하다
2)ElasticSearch와 RDB의 차이
4. 참고
1)pageable : https://hudi.blog/spring-data-jpa-pagination/