BookDonationEvent
와 Book
간의 1대다 관계에서 BookDonationEvent
중심의 페이징 쿼리 실행 시 원하는 결과를 얻지 못하는 현상이 발생했다. @GetMapping("{donationId}")
public String bookApplyDonationEventPage(Model model, @PathVariable Long donationId) {
BookDonationEvent bookDonationEvent = bookDonationEventRepository.findById(donationId).orElseThrow(
() -> new IllegalArgumentException("해당 이벤트가 존재하지 않습니다.")
);
List<Book> books = bookDonationEvent.getBooks().stream().filter(book -> book.getBookStatus().equals(BookStatusEnum.DONATION)).toList();
List<BookResponseDto> bookResponseDtos = books.stream()
.map(BookResponseDto::new)
.toList();
BookDonationEventResponseDto bookDonationEventResponseDto = new BookDonationEventResponseDto(bookDonationEvent);
model.addAttribute("bookDonationEvent", bookDonationEventResponseDto);
model.addAttribute("books", bookResponseDtos);
return "/users/bookApplyDonation";
}
@Query(value = "select bde from BookDonationEvent bde" +
" join fetch bde.books book" +
" where bde.id = :donationId and book.bookStatus = :status")
Page<BookDonationEvent> findPageByDonationId(@Param("donationId") Long donationId, @Param("status") BookStatusEnum status, Pageable pageable);
JPA의 페이징 처리는 논리적으로 간단하지만 join fetch
를 사용하면서 발생하는 문제는 각 BookDonationEvent
가 여러 Book
을 가질 수 있기 때문이다.
따라서 한 BookDonationEvent
내부의 여러 Book
들이 페이징 처리의 대상이 되면서 원하는 페이징 결과를 얻기 어려웠던 것 같다.
BookDonationEvent
를 중심으로 페이징하는 대신 직접적으로 Book
을 조회하는 방식으로 쿼리를 변경하여 문제를 해결했다.
이 방식을 사용하면 BookDonationEvent
에 종속되지 않고 원하는 조건과 함께 Book
만을 페이징 처리하여 결과를 얻을 수 있다.