[QueryDSL] BooleanExpression을 통한 복잡한 동적쿼리 표현(BooleanBuilder 제거)

안녕하세요.

 

오늘은 BooleanExpression을 통해서 QueryDSL Repository의 표현을 좀더 직관적으로 볼 수 있도록 리팩토링하는 과정을 소개해보고자 합니다.

 

사실 이부분에 대해서는 그동안 BooleanBuilder라는 객체를 활용해서 where 절에 들어올 쿼리문을 생성했는데요.

 

여러 if절에 의해 다음과 같이 쿼리의 형태를 전혀 예상할 수 없을 정도로 바뀌었습니다.

 

BooleanBuilder를 활용한 repository 메소드
public List<Study> findLiveStudyBySearch(String title, Integer bigCity, Integer smallCity) {
    BooleanBuilder builder = new BooleanBuilder();
    if (StringUtils.isNotBlank(title)) { // 제목 검색
        builder.and(study.title.contains(title));
    }
    if (bigCity != null) { // 시도 검색
        builder.and(study.bigCity.eq(bigCity));
    }
    if (smallCity != null) { // 시군구 검색
        builder.and(study.smallCity.eq(smallCity));
    }
    builder.and(study.deleted.eq(false)); // 삭제여부 false

    return jpaQueryFactory.selectFrom(study)
                          .where(builder)
                          .fetch();
}

파라미터로 넘어온 title, bigCity, smallCity라는 검색조건의 유무에 따라 if절에서 조건을 따로 넣어주는 형태로 할 수 밖에 없었는데요.

 

BooleanExpression을 활용하면 어떻게 변할수 있는지 확인해 보시죠!!

 


BooleanExpression을 활용한 리팩토링
public List<Study> findLiveStudyBySearch(String title, Integer bigCity, Integer smallCity) {
    return jpaQueryFactory.selectFrom(study)
                          .where(eqTitle(title),
                                 eqBigCity(bigCity),
                                 eqSmallCity(smallCity),
                                 eqDeleted(false))
                          .fetch();
}

- eqTitle, eqBigCity, eqSmallCity, eqDeleted 라는 메소드를 추가적으로 생성하여 BooleanExpression 타입을 리턴하도록 합니다. 

- 결과적으로 코드는 길어졌지만 만약 재사용성까지 고려한다면 기꺼이 하지 않을 이유가 없어보입니다.

- 또한 한순간에 study라는 도메인에서 title, bigCity, smallCity, deleted 라는 컬럼의 검색이 이루어진다는 것을 파악할 수 있습니다.

 

아래는 추가적으로 정의한 BooleanExpression 타입을 리턴하는 메소드입니다.

 

    private BooleanExpression eqTitle(String title) {
        if (StringUtils.isBlank(title)) {
            return null;
        }
        return study.title.containsIgnoreCase(title);
    }

    private BooleanExpression eqBigCity(Integer bigcity) {
        if (bigcity != null) {
            return null;
        }
        return study.bigcity.eq(bigcity);
    }

    private BooleanExpression eqSmallCity(Integer smallCity)
        if (smallCity != null) {
            return null;
        }
        return study.smallCity.eq(smallCity);
    }

    private BooleanExpression eqDeleted(boolean deleted) {
        return study.deleted.eq(deleted);
    }

 


 

해당 QueryDSL에 대한 내용은 우아콘2020에서 확인할 수 있는 내용입니다. 저 또한 해당 영상을 통해서 많은 부분을 배웠기 때문에 공유드립니다.

 

감사합니다.

 

youtu.be/zMAX7g6rO_Y

 

댓글

Designed by JB FACTORY