제가 처음 구현한 방식에서는 시작일 또는 종료일을 지정하지 않은 경우, 모든 기간의 Todo가 검색되는 일이 생겼습니다.
기간을 둘 다 넣은 경우 : 정상 작동
(생성 날짜와 title을 같게 세팅했습니다.)

둘 중 하나라도 넣지 않은 경우, 시작일 이전 또는 종료일 이후의 결과도 나오고 있습니다.

코드
처음에 between 메서드로 기간 검색을 구현한 코드
(시작일 또는 종료일 둘 중 하나라도 없으면 기간 검색 자체가 되지 않음)
@Override
public Page<TodoSearchResponse> searchTodo(Pageable pageable, String title, LocalDateTime startDateTime, LocalDateTime endDateTime, String nickname){
QTodo todo = QTodo.todo;
QManager manager = QManager.manager;
QComment comment = QComment.comment;
QUser user = QUser.user;
List<TodoSearchResponse> query = queryFactory
.select(Projections.constructor(TodoSearchResponse.class,
todo.title,
manager.countDistinct(),
comment.countDistinct()))
.distinct()
.from(todo)
.leftJoin(todo.managers, manager)
.leftJoin(todo.comments, comment)
.leftJoin(todo.user, user)
.offset(pageable.getOffset())
.where(
titleContains(title),
userNicknameContains(nickname),
todoDateBetween(startDateTime, endDateTime)
)
.groupBy(todo.id)
.orderBy(todo.createdAt.desc())
.limit(pageable.getPageSize())
.fetch();
return new PageImpl<>(query, pageable, query.size());
}
private BooleanExpression titleContains(String titleKeyword) {
return titleKeyword != null ? todo.title.contains(titleKeyword) : null;
}
private BooleanExpression userNicknameContains(String managerNickname) {
return managerNickname != null ? user.nickname.contains(managerNickname) : null;
}
private BooleanExpression todoDateBetween(LocalDateTime startDate, LocalDateTime endDate) {
return startDate != null && endDate != null ? todo.createdAt.between(startDate, endDate) : null;
}
개선된 코드(시작일 또는 종료일 둘 중 하나만 주어지더라도 정상적으로 검색 가능)
@Override
public Page<TodoSearchResponse> searchTodo(Pageable pageable, String title, LocalDateTime startDateTime, LocalDateTime endDateTime, String nickname){
QTodo todo = QTodo.todo;
QManager manager = QManager.manager;
QComment comment = QComment.comment;
QUser user = QUser.user;
List<Todo> todos = queryFactory
.select(todo)
.from(todo)
.leftJoin(todo.managers, manager)
.leftJoin(todo.comments, comment)
.leftJoin(todo.user, user)
.offset(pageable.getOffset())
.where(
titleContains(title),
userNicknameContains(nickname),
startDateTime != null ? todo.createdAt.gt(startDateTime) : null,
endDateTime != null ? todo.createdAt.lt(endDateTime) : null
)
.groupBy(todo.id)
.orderBy(todo.createdAt.desc())
.limit(pageable.getPageSize())
.fetch();
List<TodoSearchResponse> dtoList = todos.stream()
.map(t -> new TodoSearchResponse(
t.getTitle(),
t.getManagers().size(),
t.getComments().size()))
.collect(Collectors.toList());
return new PageImpl<>(dtoList, pageable, dtoList.size());
}
private BooleanExpression titleContains(String titleKeyword) {
return titleKeyword != null ? todo.title.contains(titleKeyword) : null;
}
private BooleanExpression userNicknameContains(String managerNickname) {
return managerNickname != null ? user.nickname.contains(managerNickname) : null;
}
개선 후 포스트맨
시작일 이전의 게시물이 검색되지 않음

종료일 이후의 게시물이 검색되지 않음

'트러블 슈팅' 카테고리의 다른 글
| fetchJoin와 BatchSize를 같이 사용한 경우의 경고문 (0) | 2024.10.11 |
|---|---|
| QueryDsl에서 List<Dto> 방식과 List<Entiry> 방식 (0) | 2024.10.11 |
| @AuthenticationPrincipal AuthUser authUser 에서 NullPointerException 발생 문제 (0) | 2024.10.11 |
| 테이블 이름이 예약어와 같은 경우의 에러 ( 테이블 이름 order ) (0) | 2024.09.21 |
| [깃 파일 권한 문제] warning: unable to access … Permission denied (1) | 2024.09.21 |