QueryDsl에서 날짜 타입 Parsing 하기

메밀·2024년 8월 21일

통계 기능을 구현하는데, 한 엔드포인트에서 조건에 따라 2024-08-21 혹은 2024-08-21 01:00 등으로 날짜를 파싱할 일이 생겼다.

결론: DateTemplate을 사용하면 된다

// 사용 방법
Expressions.dateTemplate("반환할 타입 Class", "template 포맷", "인자")
// 사용 예시
Expressions.dateTemplate(String.class, "DATE_FORMAT({0}, '%Y-%m-%d')", article.createdAt)

template으로는 정말 자주 쓰지만 절대 외워지지는 않는 정규식을 적어주면 된다.

완성 코드


@RequiredArgsConstructor
@Repository
public class ArticleQueryRepository {
    private final JPAQueryFactory queryFactory;

    /**
     * 게시글 통계 조회
     *
     * @param statisticRequest 통계 요청 정보
     * @return 통계 결과 리스트
     */
    public List<StatisticResponse> getStatistics(StatisticRequest statisticRequest) {
        // 통계 요청 타입(일별, 시간대별)에 맞는 날짜 템플릿 생성
        DateTemplate<String> dateTemplate = getDateTemplateByStatisticType(statisticRequest.getType());

        return queryFactory
                .select(
                        new QStatisticResponse(
                                dateTemplate,
                                getExpression(statisticRequest.getValue())
                        )
                )
                .from(hashtags)
                .join(hashtags.article, article)
                .where(
                        hashtags.name.eq(statisticRequest.getHashtag())
                                .and(article.createdAt.between(statisticRequest.getStart(), statisticRequest.getEnd()))
                )
                .groupBy(dateTemplate)
                .fetch();
    }

    /**
     * 통계 요청 타입(일별, 시간대별)에 맞는 날짜 템플릿 반환
     *
     * @param type date, hour
     * @return 날짜 템플릿
     */
    private DateTemplate<String> getDateTemplateByStatisticType(StatisticType type) {
        String template = type == StatisticType.DATE
                ? "DATE_FORMAT({0}, '%Y-%m-%d')" // 일별 통계의 경우 날짜만 반환하는 템플릿
                : "DATE_FORMAT({0}, '%Y-%m-%d %H:00')"; // 시간대별 통계의 경우 시간까지 반환하는 템플릿

        return Expressions.dateTemplate(String.class, template, article.createdAt);
    }

    /**
     * 통계 요청 값(게시글 수, 좋아요 수 등)에 맞는 표현식을 반환
     *
     * @param value 통계 값 타입 (COUNT, LIKE_COUNT, SHARE_COUNT, VIEW_COUNT)
     * @return
     */
    private NumberExpression<Integer> getExpression(StatisticValue value) {
        return switch (value) {
            case COUNT -> article.count().intValue();
            case LIKE_COUNT -> article.likeCount.sum();
            case SHARE_COUNT -> article.shareCount.sum();
            case VIEW_COUNT -> article.viewCount.sum();
            default -> throw new IllegalArgumentException(INVALID_STATISTIC_VALUE);
        };
    }
}

0개의 댓글