반응형

아래와 같은 게시물이 DB에 저장되었다고 가정하겠습니다.

5

4

3

2

1

만약 한 번에 2개씩 불러온다면, 5~4번을 불러올 수 있습니다.

그 다음에는 3~2번, 그 다음에는 1번을 불러올 수 있습니다.

1번을 불러왔을 때는 더 이상 다음 조회할 게시물이 없다는 사실을 알아야합니다.

저는 위 예시를 기준으로 설명하면, 다음 방법으로 구현하였습니다.

1. 일단 두 개를 불러온다. (+ 더 조회할 게시물이 있는지)

2. 불러온 게시물의 마지막 ID값을 기억한다.(위 예시로 보면 4번)

3. 스크롤이 끝에 닿으면, ID값이 4번 "미만"인 게시물 2개를 불러온다. ( + 더 조회할 게시물이 있는지)

4. 불러온 게시물의 마지막 ID값을 기억한다.(위 예시로 보면 2번)

5. 스크롤이 끝에 닿으면, ID 값이 2번 "미만"인 게시물 2개를 불러온다. ( + 더 조회할 게시물이 있는지)

6. 불러온 게시물의 마지막 ID값을 기억한다.(위 예시로 보면 1번)

7. 스크롤이 끝에 닿아도, 5번에서 이미 더 조회할 게시물이 없다는 사실을 알고있으므로 더이상 불러올 수 없다.

위처럼 조회하는 JPQL 코드는 아래와 같습니다.

@Query("select h from History h join fetch h.seller join fetch h.buyer join fetch h.ticket " +
        "where h.buyer.id = :userId and h.id < :lastHistoryId order by h.createdAt desc")
Slice<History> findNextPurchaseHistoriesByUserIdOrderByCreatedAt(@Param("userId") Long userId, @Param("lastHistoryId") Long lastHistoryId, Pageable pageable);

잡다한 코드가 섞여있는데, 결국 작성일자 순으로 내림차순 하고, where 절에 "h.id < :lastHistoryId"를 이용하여 다음으로 불러올 게시물을 알아낸 것입니다.

게시물을 몇 개씩 불러올지는 Pageable에 담겨있습니다.

반환형은 Slice로 하였는데, 이를 통해 별도의 카운트 쿼리를 호출하지 않고, 원래 갯수보다 1개 더 불러와서 다음에 조회할 게시물이 더 있는지 확인할 수 있습니다.

위 쿼리를 호출한 서비스 메소드의 코드는 아래와 같습니다.

return historyRepository.findNextSalesHistoriesByUserIdOrderByCreatedAt(userId, lastHistoryId != null ? lastHistoryId : Long.MAX_VALUE, PageRequest.of(0, limit))
        .map((Function<History, HistoryDto>) h -> convertHistoryToDto(h));

Pageable에는 "PageRequest.of(0, limit)"를 넘겨주었습니다. 0번 페이지에서 limit개수만큼 가져오게 됩니다.

Slice를 다른 dto로 변환할 때는, 위처럼 map을 이용하면 됩니다.

다음에 더 불러올 게시물이 있는지 확인하려면 slice.hasNext()를 호출하면 됩니다.

 

slice.map((Function<Object, ObjectDto>) o -> new ObjectDto());
slice.map(o -> new ObjectDto());

slice.hasNext();

예시 입니다.

 

오류가 있으면 지적 부탁드립니다.

반응형

+ Recent posts