[Spring] pagination

yoon·2024년 4월 1일

spring-boot

목록 보기
24/41
post-thumbnail

✅pagination

Spring Data Jpa에서 제공하는 Page와 Pageable을 이용하면 편리하게 구현할 수 있다.

  • Pageable : JPA가 DB에 접근해 데이터를 가져올 때 자동으로 limit 조건을 붙여 데이터를 가져온다.
  • PageRequest : 페이지네이션 정보를 담기위한 구현제이다.
  • Page : Pageable을 파라미터로 가져온 결과는 Page<Object>형태로 반환되며, Page를 사용하면 Page<List<Object>>의 형태를 반환한다.

✔ Repository

public interface ReviewRepository extends JpaRepository<Review, Long> {
    @Query("select ri from Review ri " +
            "where ri.item.id = :itemId " +
            "order by ri.registerTime desc")
    Page<Review> getReviewList(@Param("itemId") Long itemId, PageRequest pageRequest);
}
  • Page<Object> 로 반환을 받으면 getContent()를 통해 object를 꺼내올 수 있다.

✔ Controller

@GetMapping("/reviews/{itemId}")
    public String reviews(
            @PageableDefault(page=1) Pageable pageable,
            @PathVariable("itemId") Long itemId,
            Model model
    ){
        Page<ReviewResponseDto> reviewResponseDtos =
                reviewService.findAllByItemId(itemId,pageable)
                        .map(ReviewResponseDto::new);

        int blockLimit = 5;
        int startPage = (((int) Math.ceil(((double) pageable.getPageNumber() / blockLimit))) - 1) * blockLimit + 1;
        int endPage = Math.min((startPage + blockLimit - 1), reviewResponseDtos.getTotalPages());

        model.addAttribute("reviews",reviewResponseDtos);
        model.addAttribute("startPage", startPage);
        model.addAttribute("endPage", endPage);
        model.addAttribute("itemId",itemId);

        return "review/reviewList";
    }

✔ Service

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

public Page<Review> findAllByItemId(Long itemId,Pageable pageable){
        int page = pageable.getPageNumber()-1;
        int pageSize = 5;
        Page<Review> reviewList = reviewRepository.getReviewList(itemId,PageRequest.of(page, pageSize));
        return reviewList;
    }
  • PageRequest page = PageRequest.of(페이지 순서, 페이지 크기)
    세번째 인자로 sort혹은 direction을 사용하여 정렬을 설정할 수 있다.
// EX) 내림차순 정렬
PageRequest.of(페이지 순서, 페이지 크기, Sort.by(Direction.DESC, "price"));
PageRequest.of(페이지 순서, 페이지 크기, Sort.by(Order.desc("price")));
PageRequest.of(페이지 순서, 페이지 크기, Direction.DESC, "price");

✔ thymeleaf 구현

   <div>
        <ul class="pagination justify-content-center">
            <li class="page-item">
                <a class="page-link" th:href="@{/reviews/{itemId}(itemId=${itemId},page=1)}">첫 페이지 </a>
            </li>
            <li class="page-item">
                <a class="page-link" th:href="${reviews.first} ? '#' : @{/reviews/{itemId}(itemId=${itemId},page=${reviews.number})}"> 이전 </a>
            </li>

            <span class="page-item" th:each="page: ${#numbers.sequence(startPage, endPage)}">

                <li class="page-item active" th:if="${page == reviews.number + 1}">
                    <a class="page-link" th:text="${page}"></a>
                </li>
                <li class="page-item" th:unless="${page == reviews.number + 1}">
                    <a class="page-link" th:href="@{/reviews/{itemId}(itemId=${itemId}, page=${page})}" th:text="${page}"></a>
                </li>
            </span>
            <li class="page-item">
                <a class="page-link" th:href="${reviews.last} ? '#' : @{/reviews/{itemId}(itemId=${itemId},page=${reviews.number + 2})}"> 다음 </a>
            </li>
            <li class="page-item">
                <a class="page-link" th:href="@{/reviews/{itemId}(itemId=${itemId},page=${reviews.totalPages})}"> 마지막 페이지</a>
            </li>

        </ul>
    </div>
profile
하루하루 차근차근🌱

0개의 댓글