본문 바로가기
트러블 슈팅

기간 검색에서 시작일 또는 종료일이 없을 경우 발생한 문제 개선

by jhdevtrace 2024. 10. 11.

제가 처음 구현한 방식에서는 시작일 또는 종료일을 지정하지 않은 경우, 모든 기간의 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;
    }

 

 

 

 

개선 후 포스트맨

 

 

시작일 이전의 게시물이 검색되지 않음

 

 

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