
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", Member.class)
.setParameter("age", age)
.setFirstResult(offset)
.setMaxResults(limit)
.getResultList();
}
순수 JPA로 페이징을 한다면 위와 같이 메서드를 만들고 JPQL을 작성해야 했다.
Spring Data JPA는 이 과정을 훨씬 쉽게 구현할 수 있게 해줄 뿐 아니라,
여러 가지 기능도 갖고 있어 코드 작성을 수월하게 도와준다.
페이징을 위해서는 먼저 레파지토리에 관련 메서드를 구현해야 한다.
메서드의 반환 타입에는 Page, Slice, List 세 종류가 있다.
그 중에서 Page 타입에 대해 소개하겠다.
Page
public interface MemberRepository extends JpaRepository<Member, Long>
Page<Member> findByAge(int age, Pageable pageable);
}
레파지토리에 페이징 메서드를 구현하는 방식이다.
Pageable 자리에는 메서드를 호출할 때 PageRequest를 매개변수로 사용해서 페이징 방법을 정해줄 것이다.
반환타입을 Page로 했을 때 특징은 페이징을 하면서 자동으로 count 쿼리를 통해 TotalCount를 가져온다.
public class Test {
@Autowired
MemberRepository memberRepository;
public void paging() {
PageRequest pageRequest = PageRequest.of(1, 3, Sort.by(Sort.Direction.DESC, "userName"));
Page<Member> page = memberRepository.findByAge(10, pageRequest);
List<Member> content = page.getContent(); // page에 있는 객체를 리스트로 꺼내온다.
page.getTotalElements() // 모든 페이지의 전체 객체 수 TotalCount 를 가져온다
int pageNumber = page.getNumber() // 페이지 번호를 가져온다
int totalPages = page.getTotalPages(); // 총 페이지 갯수
boolean isFirst = page.isFirst() // 첫 페이지인지
boolean hasNext = page.hasNext // 다음 페이지가 있는지
}
}
우선 PageRequest를 생성해서 우리가 원하는 페이징 단위와 정렬 패턴을 설정해준다.
PageRequest.of(int page, int size, Sort sort) 메서드를 보자.
page에 들어가는 값은 우리가 얻길 원하는 페이지 인덱스다.
size는 페이지마다 몇 개의 값을 가질지 페이지 크기를 정해주는 부분이다.
가령, age = 10인 Member가 5명이라고 했을 때, 위 코드처럼 PageRequest로 페이징 방법 설정 후
findByAge 메서드를 통해 Member 객체를 페이징한다고 해보자.
age = 10에 해당하는 Member의 userName 컬럼을 기준으로 내림차순 된 후 처음 3개의 Member가 0번 페이지에 들어간다.
이 후 남은 2개의 Member가 1번 페이지에 들어가게 된다.
그리고 PageRequest에서 페이지 인덱스를 1로 정해줬기 때문에,
page 객체에는 남은 2개의 Member 객체가 들어있는 1번 페이지가 들어있다.
sort는 어떤 값을 기준으로 어떻게 정렬할지 정하는 부분이다.
생략 가능하며, default는 레파지토리에 값을 넣어준 순서대로 페이지에 들어간다.
바로 밑에 getContent() 메서드는 페이지의 객체를 리스트로 꺼낼 때 사용한다.
그 외의 메서드도 차례로 참고하면 된다.
주의사항
페이징 메서드의 반환타입을 Page로 사용할 때 주의할 점이 있다.
public interface MemberRepository extends JpaRepository<Member, Long>
@Query(value = "select m from Member m left join m.team t")
Page<Member> findByAge(int age, Pageable pageable);
}
Page는 자동으로 count 쿼리를 실행해 TotalCount를 가져온다고 했다.
위 코드처럼 join을 위해 @Query를 선언하게 될 경우 count 쿼리는 항상 left join을 통하게 된다.
이 경우 실무에서 쿼리가 복잡해지면서 성능 저하가 발생할 수 있다.
따라서, 성능 테스트를 해보고 이 부분이 문제가 된다면 count 쿼리를 따로 작성해줘야한다.
아래처럼 말이다.
public interface MemberRepository extends JpaRepository<Member, Long>
@Query(value = "select m from Member m left join m.team t",
countQuery = "select count(m) from Member m")
Page<Member> findByAge(int age, Pageable pageable);
}
이렇게 하면 join 없이 count를 조회하게 할 수 있다.
끝
'스프링 > JPA' 카테고리의 다른 글
[Spring Data JPA] 사용자 정의 레파지토리 생성 (0) | 2022.09.26 |
---|---|
[Spring Data JPA] Update 쿼리 사용해서 Bulk로 수정하기. (2) | 2022.09.21 |
[Spring Data JPA] @NamedQuery 없이 레파지토리에 직접 쿼리 작성하기 (2) | 2022.09.19 |
[Spring Data JPA] NamedQuery 사용하기 (0) | 2022.09.19 |
[JPA] 일대다 연관 관계 매핑 (0) | 2022.09.13 |