반응형
- 기존 JPA 페이징과 정렬
public List<Member> findByPage(int age, int offset, int limit) {
return em.createQuery("select m from Member m where m.age = :age order by m.username desc")
.setParameter("age", age)
.setFirstResult(offset)
.setMaxResults(limit)
.getResultList();
}
public long totalCount(int age) {
return em.createQuery("select count(m) from Member m where m.age = :age", Long.class)
.setParameter("age", age)
.getSingleResult();
}
Spring Data 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 쿼리 없이 결과만 반환
페이징 정렬 예제
- 검색 조건 : 나이가 10살
- 정렬 조건 : 이름으로 내림차순
- 페이징 조건 : 첫 번째 페이지, 페이지당 보여줄 데이터는 3건
public interface MemberRepository extends Repository<Member, Long> {
Page<Member> findByAge(int age, Pageable pageable);
}
// Pageble 은 인터페이스 !
// 구현체로 PageRequest 객체 사용.
//페이징 조건과 정렬 조건 설정
@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(); //다음 페이지가 있는가?
}
Slice 의 경우 모바일과 같은 View 에서 + 더보기 를 해서 가져올 때 많이 사용한다.
Page 를 사용할 때 성능의 이슈
- Total Count 를 가져오는 부분에서 많이 발생 !
- 아래 예시에서 content 를 가져올 때와 count 를 할 때 모두 join 을 하기 때문에 성능이 안 나온다.
@Query(value = "select m from Member m left join m.team")
Page<Member> findByAge(int age, Pageable pageable);
⬇️ 카운트 쿼리
countQuery 사용
@Query(
value = "select m from Member m left join m.team",
countQuery = "select count(m.username) from Member m")
Page<Member> findByAge(int age, Pageable pageable);
기능이 복잡해지거나 성능이 안 나올 때는 countQuery 를 분리해서 사용하자.
728x90
반응형