스프링 데이터 JPA에서는 페이징과 정렬을 쉽게 구현 할 수 있는 강력한 방법을 제공한다.
org.springframework.data.domain.Sort
: 정렬 인터페이스org.springframework.data.domain.Pageable
: 페이징 인터페이스 (내부에 Sort
포함)org.springframework.data.domain.Page
: count 쿼리 결과를 포함org.springframework.data.domain.Slice
: count 쿼리를 포함하지 않고 다음 페이지만 확인 가능(내부적으로 limit + 1 조회)List
: (자바 컬렉션) : count 쿼리 없이 결과만 조회할 때 사용Page<Member> findByUsername(String name, Pageable pageable); //count 쿼리 사용
Slice<Member> findByUsername(String name, Pageable pageable); //count 쿼리 사용
안함
List<Member> findByUsername(String name, Pageable pageable); //count 쿼리 사용
안함
List<Member> findByUsername(String name, Sort sort);
@Test
void paging() 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));
memberRepository.save(new Member("member6", 10));
memberRepository.save(new Member("member7", 10));
int age = 10;
PageRequest pageRequest =
PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "username"));
// when
Page<Member> page = memberRepository.findByAge(age, pageRequest);
// then
List<Member> content = page.getContent();
long totalElements = page.getTotalElements();
assertThat(content.size()).isEqualTo(3);
assertThat(page.getTotalElements()).isEqualTo(7);
assertThat(page.getNumber()).isEqualTo(0);
assertThat(page.getTotalPages()).isEqualTo(3);
assertThat(page.isFirst()).isTrue();
assertThat(page.hasNext()).isTrue();
}
PageRequest는 몇 페이지, 한 페이지의 사이즈, Sorting 방법(Option) 을 가지고 Repository에 Paging을 요청할 때(Pageable 에 요청) 사용하는 객체이다.
Page는 1부터 시작이 아니라 0부터 시작이다.
Page<T>
메서드int getNumber()
: 현재 페이지 번호int getSize()
: 페이지 당 데이터 개수int getTotalPages()
: 총 페이지 수int getNumberOfElements()
: 현재 페이지에 데이터 개수long getTotalElements()
: 전체 데이터 개수boolean hasPrevious()
: 이전 페이지 여부boolean isFirst()
: 현재 페이지가 첫 페이지 인지 여부boolean hasNext()
: 다음 페이지 존재 여부boolean isLast()
: 현재 페이지가 마지막 페이지 인지 여부Pageable nextPageable()
: 다음 페이지 객체, 다음 페이지가 없으면 nullPageable previousPageable()
: 이전 페이지 객체, 이전 페이지 없으면 nullboolean hasContent()
: 데이터 존재 여부Sort getSort()
: 정렬 정보getContent()
, get()
: 실제 컨텐츠를 가지고 오는 메서드getContent()
: List<Entity>
반환get()
: Stream<Entity>
반환<U> Slice<U> map(Function<? super T, ? extends U> converter)
: 변환기@Query(value = “select m from Member m left join m.team t”,
countQuery = “select count(m.username) from Member m”)
Page<Member> findMemberAllCountBy(Pageable pageable);
join을 사용해 Member와 Team을 같이 조회할 경우 Count 쿼리도 join을 사용해 쿼리가 나간다. 만약 Member만 Count 쿼리를 사용할 경우 위와 같이 분리해서 쿼리를 작성할 수 있다.
Page<Member> page = memberRepository.findByAge(10, pageRequest);
Page<MemberDto> dtoPage = page.map(m -> new MemberDto());
@Test
void slice() 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));
memberRepository.save(new Member("member6", 10));
memberRepository.save(new Member("member7", 10));
int age = 10;
PageRequest pageRequest =
PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "username"));
// when
Slice<Member> page = memberRepository.findSliceByAge(age, pageRequest);
// then
List<Member> content = page.getContent();
assertThat(content.size()).isEqualTo(3);
assertThat(page.getNumber()).isEqualTo(0);
assertThat(page.isFirst()).isTrue();
assertThat(page.hasNext()).isTrue();
}
Slice는 Page 인터페이스와 기능은 동일하지만 Count 쿼리를 사용하지 않기 때문에 getTotalElements()
, getTotalPages()
메소드가 존재하지 않는다. 또한 limit + 1를 자동으로 조회하기 때문에 더보기 기능을 구현할 때 사용하면 편리하다.
스프링 데이터가 제공하는 페이징과 정렬 기능을 스프링 MVC에서 편리하게 사용할 수 있다.
@GetMapping("/members")
public Page<MemberDto> list(@PageableDefault(size = 5) Pageable pageable){
Page<Member> page = memberRepository.findAll(pageable);
return page.map((member -> new MemberDto(member.getId(), member.getUsername(), null)));
}
Pageable
인터페이스를 받을 수 있다.Pageable
인터페이스, 실제는 org.springframework.data.domain.PageRequest
객체 생성/members?page=0&size=3&sort=id,desc&sort=username,desc
asc 생략 가능
) size
값은 20으로 설정되어 있다. 기본 값을 변경하고 싶은면 아래와 같은 설정으로 변경 가능하다.spring.data.web.pageable.default-page-size=20 /# 기본 페이지 사이즈/
spring.data.web.pageable.max-page-size=2000 /# 최대 페이지 사이즈/
@PageableDefault
어노테이션을 사용하면 page
,size
, sort
를 기본으로 설정 가능하다.
@GetMapping("/members")
public Page<MemberDto> list(@PageableDefault(page = 1,size = 5,sort = "username", direction = Sort.Direction.DESC) Pageable pageable){
}
@Qualifier
에 접두사명 추가 {접두사명}_xxx
/members?member_page=0&order_page=1
public String list(
@Qualifier("member") Pageable memberPageable,
@Qualifier("order") Pageable orderPageable, ...