
이런식으로 페이징이 되어있는 사이트가 많이 있다.
JPA 에서 또 Spring Data jpa 프로젝트에서는 효과적으로 페이징을 처리할 수 있게 방법을 제공한다.
제가 프로젝트 하면서 사용한 코드들인데 나중에도 기회가 되면 쓰려고 정리합니다 ㅎㅎ
먼저 querydsl을 사용하지 않고 spring data jpa를 사용할 때부터 보겠습니다.
spring data jpa 사용법은 https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation 여기를 봐주세요.

PageRequest.of에는 page(0부터 시작) size를 적어주면 됩니다.
Pageable pageable = PageRequest.of(request.getPage() - 1, request.getSize(), Sort.by(DESC, sort, "id"));
Page<Board> findByTitleContaining(String search1, Pageable pageable);
spring data jpa를 사용할 경우에는 위에 작성한 pageable을 인수로 넘겨주면 Page<>로 반환되는 함수를 자동생성해줍니다.
"content": [
{
"createdDate": "2021-10-31T21:58:22.330698",
"modifiedDate": "2021-10-31T21:58:22.330698",
"id": 1,
"memberId": 1,
"title": "신고요1",
}
],
"pageable": {
"sort": {
"sorted": true,
"unsorted": false,
"empty": false
},
"pageNumber": 0,
"pageSize": 3,
"offset": 0,
"paged": true,
"unpaged": false
},
"totalPages": 1,
"totalElements": 1,
"last": true,
"sort": {
"sorted": true,
"unsorted": false,
"empty": false
},
"size": 3,
"numberOfElements": 1,
"number": 0,
"first": true,
"empty": false
}
이런식으로 나오게 됩니다.
하지만 이렇게 나오게 되면 불편하기 때문에 저는 stream을 이용해서 dto를 이용해서 반환해줍니다.
List<BoardInfo> boardList = boardRepository.findBySearchingAndCategory(search, category, pageable)
.stream().map(board -> BoardInfo.of(board)
.collect(Collectors.toList());
하지만 spring data jpa로는 한계가 있기 때문에 querydsl을 많이 사용하는데요.
querydsl 에서 pageable을 사용하는 부분을 보도록 하겠습니다.
@Override
public Page<Board> findBySearching(String search, Pageable pageable) {
QueryResults<Board> results = queryFactory.selectFrom(board)
.where(
board.title.contains(search)
)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.orderBy(
getOrderSpecifier(pageable.getSort()).toArray(OrderSpecifier[]::new)
)
.fetchResults();
List<Board> content = results.getResults();
long total = results.getTotal();
return new PageImpl<>(content, pageable, total);
}
private List<OrderSpecifier> getOrderSpecifier(Sort sort) {
List<OrderSpecifier> orders = new ArrayList<>();
// Sort
sort.stream().forEach(order -> {
Order direction = order.isAscending() ? Order.ASC : Order.DESC;
String prop = order.getProperty();
PathBuilder orderByExpression = new PathBuilder(Board.class, "board");
orders.add(new OrderSpecifier(direction, orderByExpression.get(prop)));
});
return orders;
}
Pageable pageable = PageRequest.of(request.getPage() - 1, request.getSize(), Sort.by(DESC, sort, "id"));
pageable에서 offset을 적어주지는 않았지만 jpa의 Page가 알아서 처리해줍니다.
그래서 pageable의 offset 과 pageSize를 통해서 가지고 오고 Sort부분은 getOrderSpecifier함수를 통해서 해줍니다.

querydsl에서 orderBy는 OrderSpecifier type을 가진 것만 올 수 있습니다.
그리고 fetchResults()를 통해 가지고 온 것을 통해 List<Board>와 총 개수 total 개수를 PageImpl<>() 여기에 넣어주면 됩니다.
그리고 제가 이 과정에서 nativeQuery를 통해서 pageable작성한 것 또한 써보겠습니다. querydsl이 더 좋아보이지만 그 과정에서 삽질을 해서 ㅎㅎ 혹시 모르니까 기억해놓자는 차원에서 적어봅니다 .
@Query(value = "select b.* from board where title like CONCAT('%', ?1, '%')",
countQuery = "select count(*) from board where title like CONCAT('%', ?1, '%') or petition_title like CONCAT('%', ?1, '%')",
nativeQuery = true
)
Page<Board> findBoardPagination(String search, Pageable pageable);
사실 별거는 없고 쿼리를 잘 짠다음에 countQuery를 추가로 적어줘야합니다.
'spring boot > 기술 적용' 카테고리의 다른 글
| converter를 만들지 않고 jpa mysql에서 json 사용하기 (0) | 2022.06.28 |
|---|---|
| fetchJoin과 pagination을 같이 사용할 때 (0) | 2022.06.24 |
| MultipleBagFetchException 발생시 - fetchJoin 여러개 썼을 때 (0) | 2022.06.24 |
| @Transactional의 정의, 같은 클래스에서 호출, 예외처리 (0) | 2022.06.22 |
| Spring Boot에서 GraphQl 적용해보기 (0) | 2022.05.31 |