JPA와 Pageable을 이용한 페이징 처리, Sort, Paging...

lin·2023년 8월 23일
1

웹 개발에 필수적인 페이징 처리와 Sorting
실제 개별적으로 구현 시 겁.나. 귀찮습니다. 진짜...진짜...하기싫어....

하지만 Spring Data JPA 와 Pageable을 사용하면 페이징 구현에 따른 문제들을 쉽게 해결할 수 있다!

지금도 불편함 없이 JPA를 실무에서 활용하고 있지만, 한번쯤 그 깊은 곳 내부를 들여다보는 것도 나쁘지 않지 않을까....?

Paging의 바닥을 찾아


먼저 JpaRepository는 PagingAndSortingRepository를 extends한 인터페이스이다.

그래서 PagingAndSortingRepository를 살펴보면
Extension of CrudRepository to provide additional methods to retrieve entities using the pagination and sorting abstraction!

findAll 파라미터로 Sort, Pageable이 들어가는 것을 볼 수 있다.

Pageable

org.springFramework.data 에 위치한 인터페이스이다.
PageRequest :: Basic Java Bean implementation of Pageable.

constructor를 보면
PageRequest(int pageNumber, int pageSize, Sort sort)

페이지 조건에는 pageNumber, pageSize, Sort 를 필요로 한다.
페이징을 만들기 위해서는 PageRequest를 만들어 전달하면 된다.

PageRequest pagerRequest = PageRequest.of(page, size, Sort.by("board_no").descending());

Sort

쿼리를 위한 정렬 옵션으로, list of properties를 제공받는다.
Nested Classes의 경우
ENUM :: Sort.Direction(ASC|DESC), Sort.NullHanding ( null 핸들링 어케할건지)
Class :: Sort.Order(Sort.Direction, property) 등을 받아 생성하며, Sort에 대한 input을 제공한다.

정렬 방향을 지정하는 방법은 다양한다.

PageRequest.of(0,10, Sort.by("board_no").descending());
PageRequest.of(0,10, Sort.by(Direction.DESC, "board_no"));
PageRequest.of(0,10, Sort.by(Order.desc("board_no"));
PageRequest.of(0,10, Direction.DESC, "board_no"))'

하지만 ~~ Spring Web MVC를 사용하는 경우 좀더 편리하게 활용이 가능하다.
바로 API의 URL 파라미터로 Pageable을 넣어주면 관련 매개변수를 자동으로 바인딩해서 처리해준다는 것!

    @GetMapping("/api/v1/boards")
    public Page<BoardListResponseDto> findPage(RequestDto requestDto,
                                               @ParameterObject Pageable pageable) {
        return boardService.findPage(requestDto, pageable);
    }

Controller에서 보면 이렇게 Pageable 하나 넣어주면 알아서 잘 받아준다.

아하 그러면 정렬, 페이지 설정 등을 Pageable로 받는구나.
그러면 내부에서 슉슉 잘 동작하는구나~~

Page

A page is a sublist of a list of objects. It allows gain information about the position of it in the containing entire list.
페이지는 데이터와 해당 데이터가 페이징 처리 되면서 필요한 정보를 담고 있다.

QueryDSL에서는Page의 구현체인 PageImpl를 생성하여 반환하면 된다.

   return new PageImpl<>(result, pageable, totalCount);

QueryDSL에서의 페이징

QueryDSL에서의 동적 Sorting....

기본 JPA에서는 sort를 지정해 pageable을 전달하면 알아서 잘 해주지만,
queryDSL의 경우에는....아니다!

이렇게 하면 안되구....! 저걸 넣지않으면....pageable로 지정해준 정렬 속성이 안들어갈 것이다.
따라서....바로바로 OrderSpecifier<?>를 지정해줘야한답

Public OrderSpecifier(Order order, Expression<T> target) {
	this(order, target, NullHandling.Default);
}

생성자를 살펴보면 Sort의 order와 Expression 객체를 지정하면 된다.

        pageable.getSort().stream().forEach(sort -> {
            Order order = sort.isAscending() ? Order.ASC : Order.DESC;
            String property = sort.getProperty();

            Path<Object> target = Expressions.path(Object.class, QBoard.board, property);
			OrderSpecifier<?> orderSpecifier = new OrderSpecifier(order, target);
            query.orderBy(orderSpecifier);
        });

요런 식으로 슝슝 정렬하고.....페이징 처리를 하면 queryDSL에서도 잘 정렬할 수 있다!

profile
BE

0개의 댓글