반응형
Spring Data JPA 게시글은 대부분 인프런의 김영한님의 강의인 '실전! 스프링 데이터 JPA' 기반으로 내용을 정리했습니다.
순수 JPA 페이징과 정렬
예제를 위한 조건
- 검색 조건 : 나이 10살
- 정렬 조건 : 이름 기준 내림차순
- 페이징 조건 : 첫 번째 페이지, 페이지당 보여 줄 데이터는 3건
JPA 페이징 리포지토리 코드
- MemberJpaRepository.class
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();
}
보통 페이징 기능을 구현하면 내 페이지가 몇 번째 페이지인지 알려줄 수 있는 totalCount 메서드를 만든다. totalCount 쿼리는 findByPage와 똑같은 쿼리를 작성하면 되는데, order by가 빠진 이유는 getSingResult()이기 때문에 정렬 자체가 필요 없는 거라 성능 최적화를 위해 뺐다.
- MemberJpaRepositoryTest.class
@Test
public void paging() {
// given
memberJpaRepository.save(new Member("member1", 10));
memberJpaRepository.save(new Member("member2", 10));
memberJpaRepository.save(new Member("member3", 10));
memberJpaRepository.save(new Member("member4", 10));
memberJpaRepository.save(new Member("member5", 10));
int age = 10;
int offset = 0;
int limit = 3;
// when
List<Member> members = memberJpaRepository.findByPage(age, offset, limit);
long totalCount = memberJpaRepository.totalCount(age);
// then
assertThat(members.size()).isEqualTo(3);
assertThat(totalCount).isEqualTo(5);
}
select
member0_.member_id as member_i1_0_,
member0_.age as age2_0_,
member0_.team_id as team_id4_0_,
member0_.username as username3_0_
from
member member0_
where
member0_.age=?
order by
member0_.username desc limit ?
간단하게 페이징을 구현할 수 있다. 위 출력 로그에서 offset이 없는 이유는 offset 값이 0이기 때문에 굳이 넘길 필요가 없어서 JPA에서 알아서 뺀 것이다. offset이 0이 아닌 1 이상의 값이면 쿼리에도 offset이 보인다.
그럼 페이징은 h2 데이터베이스에서만 가능할까? 아니다! JPA는 데이터베이스 방언이란 것이 존재한다. 그래서 방언 설정만 잘해주면 JPA가 지원하는 DB일 경우 알아서 페이징 쿼리가 DB에 맞게 나갈 수 있다.
데이터베이스 방언 설정하기
- application.yml
jpa:
hibernate:
ddl-auto: create
properties:
hibernate:
dialect: org.hibernate.dialect.Oracle10gDialect
format_sql: true
# show_sql: true
application.yml 파일에 dialect 부분을 추가해주면 방언 설정이 끝난다. 방언 설정 후 다시 테스트를 돌려보면 통과가 된 걸 볼 수 있다. 왜냐면 h2 데이터베이스는 오라클의 rownum을 지원하기 때문에 따로 에러가 발생하진 않는다!
select
*
from
( select
member0_.member_id as member_id1_0_,
member0_.age as age2_0_,
member0_.team_id as team_id4_0_,
member0_.username as username3_0_
from
member member0_
where
member0_.age=?
order by
member0_.username desc )
where
rownum <= ?
반응형