문제 상황
1.
JPA 페이징 처리 문제BookDonationEvent와 Book 간의 1대다 관계에서 BookDonationEvent 중심의 페이징 쿼리 실행 시 원하는 결과를 얻지 못하는 현상이 발생했다.
커스텀 커리를 작성하였지만 정상적으로 동작하지 않는다.
도서와 event가 1대 다 관계라서 정상적으로 작동하지 않는 걸로 추정된다.
@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";
}
Java
복사
@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);
Java
복사
원인 분석
페이징 처리의 복잡성
JPA의 페이징 처리는 논리적으로 간단하지만 join fetch를 사용하면서 발생하는 문제는 각 BookDonationEvent가 여러 Book을 가질 수 있기 때문이다.
따라서 한 BookDonationEvent 내부의 여러 Book들이 페이징 처리의 대상이 되면서 원하는 페이징 결과를 얻기 어려웠던 것 같다.
해결
적절한 페이징 처리
BookDonationEvent를 중심으로 페이징하는 대신 직접적으로 Book을 조회하는 방식으로 쿼리를 변경하여 문제를 해결했다.
이 방식을 사용하면 BookDonationEvent에 종속되지 않고 원하는 조건과 함께 Book만을 페이징 처리하여 결과를 얻을 수 있다.