버그 원인 파악 중 만난 이슈로 이틀을 고민하다 해결한 게 있어 기록으로 남기려고 한다.
@Transactional(readOnly = true)
public Page<Response> getHistories(List<Long> brandIds, String startDate, String endDate, PageRequest pageRequest) {
List<MassMessageType> messageTypes = MassMessageType.getMassMessageTypeList(channelName);
LocalDateTime startTime = DateUtils.convertKstToUtcStartLocalDateTime(startDate);
LocalDateTime endTime = DateUtils.convertKstToUtcEndLocalDateTime(endDate);
if (startTime.isAfter(endTime)) {
throw BaseException.of(ApiErrorCode.BAD_REQUEST);
}
List<Response> histories = historyRepository.findHistory(brandIds, startTime, endTime, pageRequest)
.stream()
.distinct()
.collect(Collectors.toList());
Long count = historyRepository.findCountHistories(brandIds, startTime, endTime)
.orElse(0L);
return new PageImpl<>(histories, pageRequest, count);
}
// 위는 생략
List<Response> histories = historyRepository.findHistory(brandIds, startTime, endTime, pageRequest)
.stream()
.distinct()
.limit(pageRequest.getPageSize()) //여기만 추가
.collect(Collectors.toList());
Long count = historyRepository.findCountHistories(brandIds, startTime, endTime)
.orElse(0L);
// histories.size() = 15, count = 23
return new PageImpl<>(histories, pageRequest, count);
// return 되는 결과 값은 total Elements = 30으로 나왔다!!
}
내가 잘못한 것은 크게 두 가지였다.
2 페이지(page = 1)에 표기될 값을 알고 싶지만 건너뛸 데이터는 없음. 처음부터 15개로 보여줘.
-> 그렇게 뽑힌 데이터가 total을 산출할 때 아래 로직을 타게 된다.
// content.size() = 15, total = 23
public PageImpl(List<T> content, Pageable pageable, long total) {
super(content, pageable);
this.total = pageable.toOptional().filter(it -> !content.isEmpty())//
// 15 x 1 + 15 > 23 (true)
.filter(it -> it.getOffset() + it.getPageSize() > total)//
// 15 + 15 = 30
.map(it -> it.getOffset() + content.size())//
.orElse(total);
}// this.total = 30
이래서 total Elements가 자꾸 30이 나왔던 것이다!
위의 무엇이 부풀렸는지를 고치면 해결 방법이 된다!
1) param 값을 내가 원하는 페이지에 -1 해준다 (1페이지 조회 = 0, 2페이지 조회 = 1 ...)
2) skip()을 추가해준다!
그래서 최종 수정한 값은..
// 코드 일부 생략
List<Response> histories = historyRepository.findHistory(brandIds, startTime, endTime)
.stream()
.distinct()
.skip(pageRequest.getOffset())
.limit(pageRequest.getPageSize())
.collect(Collectors.toList());
Long count = historyRepository.findCountHistories(brandIds, startTime, endTime)
.orElse(0L);
return new PageImpl<>(histories, pageRequest, count);
}
total이 왜! 뻥튀기 되는지 몰랐는데 드디어 이유를 알게 되서 속이 시원했다ㅎㅎ
그리고 이 기회에 total 산출하는 식을 좀 더 들여다 봐서 재밌었다.