<TIL> 107. 검색기능 queryDSL 구현

YUJIN LEE·2023년 5월 4일
0

NETicket

목록 보기
1/3
  // Event의 title과 place에서 keyword로 검색해 page로 반환. 예매가능한 공연을 먼저 정렬 후 가장 날짜가 가장 빠른순으로 정렬
  @Query("SELECT e FROM Event e JOIN e.ticketInfo t WHERE (e.title LIKE %:keyword% OR e.place LIKE %:keyword%) ORDER BY t.isAvailable DESC, e.date ASC")
  Page<Event> findAllByTitleOrPlaceContainingAndAvailableTickets(@Param("keyword") String keyword, Pageable pageable);

이렇게 작성된 코드를

 @Override
  public Page<Event> findAllByTitleOrPlaceContainingAndAvailableTickets(String keyword, Pageable pageable) {
    QEvent qEvent = QEvent.event;

    // 키워드 공백 기준으로 분할해 여러 단어로 구성된 키워드 처리
    String[] keywords = keyword.split("\\s+");

    // 검색 조건을 조합하게 하는 builder
    BooleanBuilder builder = new BooleanBuilder();

    // 각 단어에 대해, title or place에서 대소문자 구분 없이 단어를 포함하는 event를 찾는 검색 조건
    for (String word : keywords) {
      builder.and(
          qEvent.title.containsIgnoreCase(word)
              .or(qEvent.place.containsIgnoreCase(word))
      );
    }

    // 정렬 순서 설정 - 1. 예매 가능 여부, 2. 날짜별 정렬
    OrderSpecifier<Boolean> isAvailableOrder = qEvent.ticketInfo.isAvailable.desc();
    OrderSpecifier<java.time.LocalDateTime> dateOrder = qEvent.date.asc();

    // 검색 조건에 일치하는 전체 이벤트 수 계산
    long totalCount = queryFactory.selectFrom(qEvent)
        .where(builder)
        .fetchCount();

    // 검색 조건에 일치하는 이벤트를 페이지 단위로 가져옴.
    // ticketInfo를 함께 가져오기 위해 left join 사용 후 정렬 순서 적용
    List<Event> events = queryFactory.selectFrom(qEvent)
        .leftJoin(qEvent.ticketInfo)
        .fetchJoin()
        .where(builder)
        .orderBy(isAvailableOrder, dateOrder)
        .offset(pageable.getOffset())
        .limit(pageable.getPageSize())
        .fetch();

    // 결과 PageImpl 객체로 변환해 반환
    return new PageImpl<>(events, pageable, totalCount);
  }

이렇게 queryDSL을 사용해서 바꿔보았다.
그 이유는
검색 조건이 동적이며,
여러 단어에 대해서 대소문자 구분 없이 단어를 포함하는 이벤트를 찾는 조건이 있어서이다.
왜냐면 queryDSL은 동적 쿼리에 강점이 있고, 코드의 가독성이 좋기 때문이다.
그리고 타입 세이프한 쿼리 작성으로 인해 유지보수에도 용이하다.

타입 세이프한 쿼리?

쿼리를 작성 시 컴파일 시점에 타입 검사가 이루어지는 것을 의미.
즉, 쿼리 작성 중에 발생할 수 있는 타입 오류를 미리 확인하고 수정할 수 있게 해줌.

queryDSL은 쿼리를 작성할 때 필드와 조건의 타입이 일치하는지 컴파일러가 검사하므로,
쿼리에서 발생할 수 있는 타입오류를 미리 방지할 수 있다.
=> 코드의 안정성과 유지 보수성 향상.

반면, JPQL이나 SQL 같은 문자열 기반의 쿼리 언어는
쿼리 작성 시 타입 검사가 이루어지지 않아 실행 시점에 에러가 발견될 가능성이 있고,
이로인해 디버깅의 어려워지고 유지보수가 번거로울 수 있다.

profile
인정받는 개발자가 되고싶습니다.

0개의 댓글