페이징 - 스프링 데이터 JPA

Jiwon Park·2023년 6월 6일
0
//추가 count 쿼리 결과를 포함하는 페이징
Page<Member> findByUsername(String name, Pageable pageable); 

//추가 count 쿼리 없이 limit + 1을 조회해서 다음 페이지만 확인 가능(모바일 리스트)
Slice<Member> findByUsername(String name, Pageable pageable);

//추가 count 쿼리 없이 결과만 반환
List<Member> findByUsername(String name, Pageable pageable); 

테스트

Page는 1부터 시작이 아니라 0부터 시작이다.
PageRequest 생성자의 첫 번째 파라미터에는 현재 페이지를, 두 번째 파라미터에는 조회할 데이터 수를 입력한다.

public interface MemberRepository extends JpaRepository<Member, Long> {
 	Page<Member> findByAge(int age, Pageable pageable);
}


@Test
public void page() throws Exception {
     //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));
     
     //when
     PageRequest pageRequest = PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC,"username"));
     Page<Member> page = memberRepository.findByAge(10, pageRequest);
     
     //then
     List<Member> content = page.getContent(); //조회된 데이터
     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(); //다음 페이지가 있는가?
}

count 쿼리를 다음과 같이 분리할 수도 있음(카운트는 left join 안해도 됨)

@Query(value = “select m from Member m left join m.team t”,
		countQuery = “select count(m.username) from Member m”)
Page<Member> findByAge(int age, Pageable pageable);

페이지를 유지하면서 엔티티를 DTO로 변환하기

Page<Member> page = memberRepository.findByAge(10, pageRequest);
Page<MemberDto> dtoPage = page.map(m -> new MemberDto());

사용 예시(Page 내용 DTO로 변환)

요청 파라미터
예) /members?page=0&size=3&sort=id,desc&sort=username,desc

@GetMapping("/members")
public Page<Member> list(@PageableDefault(size = 12, sort = "username", 
						   direction = Sort.Direction.DESC) Pageable pageable) {
   return memberRepository.findAll(pageable).map(MemberDto::new);
}

@Data
public class MemberDto {
     private Long id;
     private String username;
     
     public MemberDto(Member m) {
         this.id = m.getId();
         this.username = m.getUsername();
 	 }
}

글로벌 설정

spring.data.web.pageable.default-page-size=20 # 기본 페이지 사이즈
spring.data.web.pageable.max-page-size=2000 # 최대 페이지 사이즈

페이징 정보가 둘 이상이면 접두사로 구분
예) /members?member_page=0&order_page=1

@Qualifier 에 접두사명 추가 "{접두사명}_xxx”

public String list(
 @Qualifier("member") Pageable memberPageable,
 @Qualifier("order") Pageable orderPageable, ..

참고

Page 인터페이스

public interface Page<T> extends Slice<T> {

   int getTotalPages(); //전체 페이지 수
   long getTotalElements(); //전체 데이터 수
   <U> Page<U> map(Function<? super T, ? extends U> converter); //변환기
}

Slice 인터페이스

public interface Slice<T> extends Streamable<T> {

    int getNumber(); //현재 페이지
    int getSize(); //페이지 크기
    int getNumberOfElements(); //현재 페이지에 나올 데이터 수
    List<T> getContent(); //조회된 데이터
    boolean hasContent(); //조회된 데이터 존재 여부
    Sort getSort(); //정렬 정보
    boolean isFirst(); //현재 페이지가 첫 페이지 인지 여부
    boolean isLast(); //현재 페이지가 마지막 페이지 인지 여부
    boolean hasNext(); //다음 페이지 여부
    boolean hasPrevious(); //이전 페이지 여부
    Pageable getPageable(); //페이지 요청 정보
    Pageable nextPageable(); //다음 페이지 객체
    Pageable previousPageable();//이전 페이지 객체
    <U> Slice<U> map(Function<? super T, ? extends U> converter); //변환기
}
profile
안녕하세요

0개의 댓글