Spring
Querydsl 페이징과 카운터쿼리 최적화
yougeun
2023. 4. 27. 13:15
728x90
1.Page<T>로 반환
public Page<MemberTeamDto> Page(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)
.leftJoin(member.team,team)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
JPAQuery<Long> countQuery = queryFactory
.select(member.count())
.from(member)
.leftJoin(member.team, team);
return PageableExecutionUtils.getPage(content,pageable,countQuery::fetchOne);
}
content 쿼리와 count쿼리를 나눠서 작성 후 PageableExecutionUtils.getPage() 메소드에 넣어서 반환한다.
getPage() 메소드는 아래와 같은 상황일 때 count쿼리를 날리지 않고 최적화 한다.
- 페이지의 시작이면서 content 사이즈가 page 사이즈보다 작을 때
- 마지막페이지일때(Offset+컨텐츠 사이즈)
2.Slice<T>로 반환
public Slice<MemberTeamDto> Slice(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)
.leftJoin(member.team,team)
.offset(pageable.getOffset())
.limit(pageable.getPageSize()+1)
.fetch();
boolean hasNext = false;
if(content.size()>pageable.getPageSize()){
hasNext = true;
content.remove(pageable.getPageSize());
}
return new SliceImpl<>(content,pageable,hasNext);
}
Slice는 pageable.getPageSize()+1만큼 조회하여 content.size()와 pageable.getPageSize()의 크기를 비교하여 다음페이지에 데이터가 있는지 없는지를 판단하여 hasNext를 결정한다.
content,pageable,hasNext를 SliceImpl생성자의 파라미터에 넣어 반환하면 Slice로 반환 할 수 있다.
728x90