Querydsl(1)-BooleanExpression

개발하는개발자·2022년 11월 1일
0

JPA

목록 보기
2/3
post-custom-banner

JPA에 대한 공부를 진행하며 프로젝트를 진행하던 도중 복잡한 쿼리를 짜야하는 상황이 왔다.


MyBatis로 진행하게 되면 대충 다음과 같은 동적쿼리로 실행해야 원하는 값을 뽑아올 수 있었다. 여기에 부가적으로 더 많은 쿼리문이 들어가야 했고 불가능한건 아니지만 Mybatis는 Compile시점에서 Error를 도출하기 힘들기 때문에 JPA로 전환해보고자 했다.


대략적인 패키지 구조는 다음과 같으며 반환POJO로쓸 Dto,
Table entity를 정의해놓고 mapping에는 Entity<-> Dto를 변환시켜줄 mapstruct를 정의해놓았다.


위의 해당 동적 쿼리를 Querydsl을 이용해 변환시킨결과


다음과 같이 변했고 하나의 조건절에 대한 단위테스트가 가능해졌다.

public class OneononeInquiryRepositoryUtil {

    static QOneononeInquiry oneononeInquiry = QOneononeInquiry.oneononeInquiry;

    public static BooleanExpression eqServiceType(String serviceType){
        if (StringUtils.equals("", serviceType)){
            return null;
        }
        return oneononeInquiry.channelDivisioncode.eq(serviceType);
    }

    public static BooleanExpression inCategoryTypeList(List<String> categoryList){
        if(categoryList.isEmpty()){
            return null;
        }
        return oneononeInquiry.customercenterCategoryCode.in(categoryList);
    }

    public static BooleanExpression containSearchCategory(String searchCategory,String searchKeyword){

        if(StringUtils.equals("SR01", searchCategory)){
            return oneononeInquiry.registProcessorId.contains(searchKeyword);
        }
        if(StringUtils.equals("SR21", searchCategory)){
            return oneononeInquiry.title.contains(searchKeyword);
        }
        return (oneononeInquiry.registProcessorId.contains(searchKeyword).or(oneononeInquiry.title.contains(searchKeyword)));
    }

    public static BooleanExpression betweenReferenceDay(String startDay, String endDay){

        if(!StringUtils.equals(startDay, "")){
            return oneononeInquiry.registProcessDayandtime.between(startDay,endDay);
        }

        return oneononeInquiry.registProcessDayandtime.lt(endDay);

    }

    public static OrderSpecifier<String> orderByReferenceDayFirst(String referenceDay){

        StringPath aliasQuantity = Expressions.stringPath("lastAnswerDay");

        if(StringUtils.equals("최종문의일",referenceDay)){
            return aliasQuantity.desc();
        }
        return oneononeInquiry.registProcessDayandtime.desc();
    }

    public static OrderSpecifier<String> orderByReferenceDaySecond(String referenceDay){

        StringPath aliasQuantity = Expressions.stringPath("lastAnswerDay");

        if(StringUtils.equals("최종문의일",referenceDay)){
            return aliasQuantity.desc();
        }
        return oneononeInquiry.registProcessDayandtime.desc();
    }


}

Util클래스로 빼내어 정적 메서드로 사용할 수 있게 만드는것이 리팩토링, 관리면에서 더 편리하다고 생각했다. 코드를 보면 조건절을 이용해 원하는 쿼리를 반환하거나 Null을 반환해 해당 쿼리가 실행하지 않도록 할 수 있다.

TDD 관점에서 개발시 사용하지 않을 이유가 없다고 생각한다. 복잡한 Domain에서 JPA사용이 힘들시 Mybatis와 혼용하여 사용하면 더 좋을 것 같다.

profile
하루에 하나씩 배우자
post-custom-banner

0개의 댓글