!!SpringDataJpa에서 제공하는 페이징 처리를 할때 첫번째는 0부터 시작한다.
@Test
void paging() {
//given
memberRepository.save(new Member("member1", 10));
memberRepository.save(new Member("member2", 10));
memberRepository.save(new Member("member3", 10));
memberRepository.save(new Member("member4", 10));
memberRepository.save(new Member("member5", 10));
int age = 10;
//이름순으로 정렬된 값을 가져옴 첫번째 파라미터는 페이지번호, 두번째 파라미터는 사이즈
final PageRequest pageRequest = PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "username"));
//when
//반환 타입이 Page면 totalCount쿼리까지 같이 날린다.
final Page<Member> page = memberRepository.findByAge(age, pageRequest);
//일반적인 페이징처리방법. 데이터가 뒤에 더있고 상관없이 내가 정한 갯수만큼만 페이징처리함
List<Member> page1 = memberRepository.findByAge1(age, pageRequest);
//반환 타입이 Slice totalCount를 날리지 않는다.
Slice<Member> page2 = memberRepository.findByAge2(age, pageRequest);
//then
final List<Member> content = page.getContent();
final long totalElements = page.getTotalElements();
System.out.println("totalElements = " + totalElements);
assertThat(content.size()).isEqualTo(3);
assertThat(page.getTotalElements()).isEqualTo(5);
assertThat(page.getNumber()).isEqualTo(0);
assertThat(page.getTotalPages()).isEqualTo(2);
assertThat(page.isFirst()).isTrue();
assertThat(page.hasNext()).isTrue();
//Slice는 토탈카운트를 제공하지 않는다. 그리고 페이징 사이즈도 내가 정한것에 +1을 해서 보내줌. (모바일 환경에서 더보기 버튼 같은 기능제공)
assertThat(content.size()).isEqualTo(3);
assertThat(page2.getNumber()).isEqualTo(0);
assertThat(page2.isFirst()).isTrue();
assertThat(page2.hasNext()).isTrue();
}
인터페이스
Page<Member> findByAge(int age, Pageable pageable);
List<Member> findByAge1(int age, Pageable pageable);
Slice<Member> findByAge2(int age, Pageable pageable);
페이징처리에 매우 편리한 기능을 제공한다.
그런데 만약 복잡한 쿼리를 쓸때 카운트쿼리가 섞여있으면 성능에 매우 안좋다고 한다. 카운트쿼리는 그냥 불러오기만하면 되는데 괜히 섞여있어서 조인이 일어날때 쓸때없이 카운트쿼리까지 가져오고 하는건 별로인가보다.
@Query(value = "select m from Member m left join m.team t",
countQuery = "select count(m) from Member m")
List<Member> findByAge1(int age, Pageable pageable);
그래서 이런식으로 카운트쿼리만 따로 분리할 수 있다.
그런데
final Page<Member> page = memberRepository.findByAge(age, pageRequest);
이상태로 responseBody로 내보내면 위험하니까 (엔티티보단 Dto로 변환해서 내보내는게 안전하고 좋다.) 그것까지도 Page가 제공해준다.
responseBody로 내보내기 위해 Page는 map()이라는 메소드를 제공한다.
final Page<MemberDto> toMap = page.map(m -> new MemberDto(m.getId(), m.getUsername(), null));
뭐 stream.map()을 이용해도 될것 같은데 아무튼 더 편리하게 사용할 수 있는것 같다.
'SpringDataJPA' 카테고리의 다른 글
Auditing (1) | 2022.12.02 |
---|---|
페치조인 정리 (0) | 2022.11.30 |
@Query (0) | 2022.11.29 |
NamedQuery (0) | 2022.11.29 |
@EntityGraph (0) | 2022.10.30 |