오봉이와 함께하는 개발 블로그
Querydsl - 스프링 데이터 페이징 활용 1 (Querydsl 페이징 연동) 본문
728x90
스프링 데이터 페이징 활용1 - Querydsl 페이징 연동
- 스프링 데이터의 Page, Pageable을 활용해보자.
- 전체 카운트를 한번에 조회하는 단순한 방법
- 데이터 내용과 전체 카운트를 별도로 조회하는 방법
사용자 정의 인터페이스에 페이징 2가지 추가
public interface MemberRepositoryCustom {
List<MemberTeamDto> search(MemberSearchCondition condition);
Page<MemberTeamDto> searchPageSimple(MemberSearchCondition condition, Pageable pageable);
Page<MemberTeamDto> searchPageComplex(MemberSearchCondition condition, Pageable pageable);
}
전체 카운트를 한번에 조회하는 단순한 방법
searchPageSimple(), fetchResults() 사용
@Override
public Page<MemberTeamDto> searchPageSimple(MemberSearchCondition condition, Pageablepageable) {
QueryResults<MemberTeamDto> results = queryFactory
.select(new QMemberTeamDto(
member.id,
member.username,
member.age,
team.id,
team.name
))
.from(member)
.leftJoin(member.team, team)
.where(
usernameEq(condition.getUsername()),
teamNameEq(condition.getTeamName()),
ageGoe(condition.getAgeGoe()),
ageLoe(condition.getAgeLoe()))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetchResults();
List<MemberTeamDto> content = results.getResults();
long total = results.getTotal();
return new PageImpl<>(content, pageable, total);
}
.offset()
: 몇 번째부터 시작할지.limit()
: 한 번 조회할 때 몇 개를 조회할지(한 페이지에 데이터 몇 개를 조회할지)getResults()
: 쿼리 결과에서 실제 컨텐츠를 DTO에 넣어주는 메소드
Querydsl이 제공하는 fetchResults()
를 사용하면 내용과 전체 카운트를 한번에 조회할 수 있다.(실제 쿼리는 2번 호출 - 카운트 쿼리, 페이징 쿼리)fetchResult()
는 카운트 쿼리 실행시 필요없는 order by
는 제거한다.
테스트
@Test
void searchPageSimple() {
Team teamA = new Team("teamA");
Team teamB = new Team("teamB");
em.persist(teamA);
em.persist(teamB);
Member member1 = new Member("member1", 10, teamA);
Member member2 = new Member("member2", 20, teamA);
Member member3 = new Member("member3", 30, teamB);
Member member4 = new Member("member4", 40, teamB);
em.persist(member1);
em.persist(member2);
em.persist(member3);
em.persist(member4);
MemberSearchCondition condition = new MemberSearchCondition();
PageRequest page = PageRequest.of(0, 3); // page 인덱스(0번부터 가져온다는 뜻), size(한페이지에 컨텐츠가 몇 개가 담기냐는 뜻)
Page<MemberTeamDto> result = memberRepository.searchPageSimple(condition, page);
assertThat(result.getSize()).isEqualTo(3);
assertThat(result.getContent()).extracting("username").containsExactly("member1","member2", "member3");
}
-- 카운트 쿼리
select
count(member0_.member_id) as col_0_0_
from
member member0_
left outer join
team team1_
on member0_.team_id=team1_.team_id
-- 페이징 쿼리
select
member0_.member_id as col_0_0_,
member0_.username as col_1_0_,
member0_.age as col_2_0_,
team1_.team_id as col_3_0_,
team1_.name as col_4_0_
from
member member0_
left outer join
team team1_
on member0_.team_id=team1_.team_id limit ?
데이터 내용과 전체 카운트를 별도로 조회하는 방법
직접 total count 쿼리를 날리는 방법이다.
상황에 따라 다르지만, 예를 들어 count가 테이블에 데이터로 있다거나, join을 좀 줄여서 해도 count값에 변함이 없다거나 하는 등 count 쿼리를 줄일 수 있을 때가 있다.
전체 카운트를 조회하는 방법을 최적화 할 수 있으면 이렇게 분리해서 사용하자.
성능 최적화에 상당한 효과를 얻을 수 있을 것이다.
또, 코드를 리펙토링해서 내용 쿼리과 전체 카운트 쿼리를 읽기 좋게 분리하면 좋다.(메소드화 시킨다.)
searchPageComplex()
/**
* 복잡한 페이징
* 데이터 조회 쿼리와, 전체 카운트 쿼리를 분리
**/
@Override
public Page<MemberTeamDto> searchPageComplex(MemberSearchCondition condition, Pageablepageable) {
// content만 가져옴.
List<MemberTeamDto> content = queryFactory
.select(new QMemberTeamDto(
member.id,
member.username,
member.age,
team.id,
team.name
))
.from(member)
.leftJoin(member.team, team)
.where(
usernameEq(condition.getUsername()),
teamNameEq(condition.getTeamName()),
ageGoe(condition.getAgeGoe()),
ageLoe(condition.getAgeLoe()))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
// total count 쿼리
long total = queryFactory
.select(member)
.from(member)
.leftJoin(member.team, team)
.where(
usernameEq(condition.getUsername()),
teamNameEq(condition.getTeamName()),
ageGoe(condition.getAgeGoe()),
ageLoe(condition.getAgeLoe()))
.fetchCount();
return new PageImpl<>(content, pageable, total);
}
인프런 김영한 지식공유자님 강의 : 실전! Querydsl
728x90
'BE > JPA' 카테고리의 다른 글
Querydsl - 스프링 데이터 페이징 활용 3 (컨트롤러 개발) (1) | 2022.09.20 |
---|---|
Querydsl - 스프링 데이터 페이징 활용 2 (CountQuery 최적화) (0) | 2022.09.20 |
Querydsl - 스프링 데이터 JPA 사용자 정의 리포지토리 (0) | 2022.09.20 |
Querydsl - 스프링 데이터 JPA 리포지토리로 변경 (1) | 2022.09.20 |
Querydsl - 조회 API 컨트롤러 개발 (0) | 2022.09.20 |
Comments