기본적인 페이징 방식
- countQuery를 날려 totalCount 체크
- 기존 fetchResults()가 Deprecated 되면서 아래 방식으로 해결
@Repository
@RequiredArgsConstructor
public class ItemRepository {
private final JPAQueryFactory jpaQueryFactory;
public Page<Item> getItems(Pageable pageable) {
List<Item> items = jpaQueryFactory
.selectFrom(item)
.offset(pageable.getOffset())
.limit(pageable.getPageSize());
long totalCount = jpaQueryFactory
.select(item.count())
.fetchOne();
return new PageImpl<>(items, pageable, totalCount);
}
}
향상된 페이징 방식
- 아래의 조건에 해당되는 경우 countQuery를 날릴 필요가 없음
- 첫 페이지이면서, 결과 사이즈가 페이지 사이즈보다 작은 경우
- 마지막 페이지인 경우
PageableExecutionUtils
사용하여 아래와 같이 적용 가능- countQuery를 직접 날리지 않고 LongSupplier로 넘겨 활용
- 활용 상세 로직은 아래 아래 PageableExecutionUtils 참고
@Repository
@RequiredArgsConstructor
public class ItemRepository {
private final JPAQueryFactory jpaQueryFactory;
public Page<Item> getItems(Pageable pageable) {
List<Item> items = jpaQueryFactory
.selectFrom(item)
.offset(pageable.getOffset())
.limit(pageable.getPageSize());
JPAQuery<Long> countQuery = jpaQueryFactory.select(item.count());
return PageableExecutionUtils.getPage(items, pageable, countQuery::fetchOne);
}
}
PageableExecutionUtils
- 첫 페이지이면서, fetchSize < pageSize인 경우
- fetchSize = totalSize
- 마지막 페이지인 경우
- pageable.getOffset() + fetchSize = totalSize
- pageable.getOffset() -> page * size
- pageable.getOffset() + fetchSize = totalSize
package org.springframework.data.support;
...
public abstract class PageableExecutionUtils {
private PageableExecutionUtils() {}
...
public static <T> Page<T> getPage(List<T> content, Pageable pageable, LongSupplier totalSupplier) {
Assert.notNull(content, "Content must not be null");
Assert.notNull(pageable, "Pageable must not be null");
Assert.notNull(totalSupplier, "TotalSupplier must not be null");
if (pageable.isUnpaged() || pageable.getOffset() == 0) { // 첫 페이지인 경우,
if (pageable.isUnpaged() || pageable.getPageSize() > content.size()) { // 결과 사이즈가 페이지 사이즈 보다 작다면
return new PageImpl<>(content, pageable, content.size()); // countQuery 호출 X
}
return new PageImpl<>(content, pageable, totalSupplier.getAsLong()); // countQuery 호출 O
}
if (content.size() != 0 && pageable.getPageSize() > content.size()) { // 마지막 페이지인 경우,
return new PageImpl<>(content, pageable, pageable.getOffset() + content.size()); // countQuery 호출 X
}
return new PageImpl<>(content, pageable, totalSupplier.getAsLong()); // countQuery 호출 O
}
}
참고
'개발 > Spring' 카테고리의 다른 글
Spring Security와 JWT를 통한 인증 및 인가 (1) | 2022.09.28 |
---|---|
Redis를 통한 JWT Refresh Token 관리 (4) | 2022.02.11 |
Refresh Token 발급과 Access Token 재발급 (5) | 2022.02.11 |
발급받은 JWT로 요청하기 (0) | 2022.02.11 |
[Spring] SecurityContext에 사용자 정보 넣어 테스트하기 (0) | 2022.02.10 |