-
[Spring] QueryDsl 페이징 쿼리 사용법JAVA/Spring(Springboot) 2023. 4. 8. 23:13728x90
QueryDsl로 페이징 쿼리를 작성할 때 count 쿼리를 분리해서 사용하면 성능이 개선되는 경우가 있다.
count 쿼리를 분리해서 작성하는 법을 알아보자.우선 return 타입으로
PageImpl 방식과 PageableExecutionUtils.getPage 방식이 있다.
PageImpl 방식은 totalCount를 구하는 쿼리를 무조건 실행하게 되지만,
PageableExecutionUtils.getPage 방식은 필요한 경우에만 totalCount를 실행하게 할 수 있다.totalCount 쿼리 실행이 필요없는 경우는 생략해서 처리한다.
- 페이지 시작이면서 컨텐츠 사이즈가 페이지 사이즈보다 작을 때
- 마지막 페이지일 때 (offset + 컨텐츠 사이즈를 더해서 전체 사이즈 구함)코드를 살펴보자
PageImple - total count 쿼리 실행
@Override public Page<MemberTeamDto> searchPageComplex(MemberSearchCondition condition, Pageable pageable) { List<MemberTeamDto> content = queryFactory .select(new QMemberTeamDto( member.id.as("memberId"), member.username, member.age, team.id.as("teamId"), team.name.as("teamName") )) .from(member) .join(member.team, team) .where(usernameEq(condition.getUsername()), teamNameEq(condition.getTeamName()), ageGoe(condition.getAgeGoe()), ageLoe(condition.getAgeLoe())) .offset(pageable.getOffset()) .limit(pageable.getPageSize()) .fetch(); int total = queryFactory .selectFrom(member) .join(member.team, team) .where(usernameEq(condition.getUsername()), teamNameEq(condition.getTeamName()), ageGoe(condition.getAgeGoe()), ageLoe(condition.getAgeLoe())) .fetch().size(); return new PageImpl<>(content, pageable, total); }
PageableExecutionUtils.getPage - 필요할 때만 totalCount 쿼리 실행
@Override public Page<MemberTeamDto> searchPageComplex(MemberSearchCondition condition, Pageable pageable) { List<MemberTeamDto> content = queryFactory .select(new QMemberTeamDto( member.id.as("memberId"), member.username, member.age, team.id.as("teamId"), team.name.as("teamName") )) .from(member) .join(member.team, team) .where(usernameEq(condition.getUsername()), teamNameEq(condition.getTeamName()), ageGoe(condition.getAgeGoe()), ageLoe(condition.getAgeLoe())) .offset(pageable.getOffset()) .limit(pageable.getPageSize()) .fetch(); JPAQuery<Member> countQuery = queryFactory .selectFrom(member) .join(member.team, team) .where(usernameEq(condition.getUsername()), teamNameEq(condition.getTeamName()), ageGoe(condition.getAgeGoe()), ageLoe(condition.getAgeLoe())); // count 쿼리가 필요없는 경우는 실행하지 않는다 return PageableExecutionUtils.getPage(content, pageable, () -> countQuery.fetch().size()); }
fetchResults() - 조회 + totalCount 쿼리 모두 실행시키고 싶을 때
@Override public Page<MemberTeamDto> searchPageSimple(MemberSearchCondition condition, Pageable pageable) { QueryResults<MemberTeamDto> results = queryFactory .select(new QMemberTeamDto( member.id.as("memberId"), member.username, member.age, team.id.as("teamId"), team.name.as("teamName") )) .from(member) // entity가 아닌 dto로 조회하면 지연로딩을 사용할 수 없기 때문에 N + 1 문제가 일어나지 않는다 .join(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); }
728x90728x90'JAVA > Spring(Springboot)' 카테고리의 다른 글