Enum과 Function을 사용하여 QueryDSL 검색 구현하기

recordsbeat·2020년 5월 18일
4
post-thumbnail
post-custom-banner

기본적인 검색은 대부분 이렇다.

검색 조건과 keyword를 함께 던져 버리기.

그럼 서버에서는 어떻게 반응할까?

이전 QueryDSL에서 where조건 추가를 살펴봤다.

QueryResults<Reservation> result = queryFactory
                .selectFrom(reservation)
                .where(
                        eqCity(search.getCityCode()),
                        
                )
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetchResults();
                
private BooleanExpression eqCity(CityCode cityCode) {
        if (ObjectUtils.isEmpty(cityCode)) {
            return null;
        }
        return reservation.city.code.eq(cityCode);
    }

도시 정보를 통해 조건을 추가할 때 Qdomain을 사용한 BooleanExpression을 사용했다.

그렇다면 검색타입(ex) 이름, 이메일, 전화번호)을 사용해 where 조건을 추가하려면?

요렇게 하면 된다.!

private BooleanExpression eqKeyWord(ReservationSearchType searchType, String keyWord){
        if(StringUtils.isBlank(keyWord)) {
            return null;
        }
        if(searchType.equals(ReservationSearchType.REG_USER_NAME))
            return reservation.user.name.firstName.contains(keyWord);


        if(searchType.equals(ReservationSearchType.REG_USER_EMAIL))
            return reservation.user.email.contains(keyWord);


        if(searchType.equals(ReservationSearchType.REG_USER_PHONE))
            return reservation.user.phoneNumber.phoneNumber.contains(keyWord);
        
        
        return searchType.getEq(keyWord);
    }

가 아니다.

일단 나는 if가 많아지면 불안하다. 그리고 검색조건이 늘어날 때 마다 일일히 조건절을 추가 해주어야한다.

좀 더 나은 방향으로

참조링크
이동욱님의 Java Enum 활용기
https://woowabros.github.io/tools/2017/07/10/java-enum-uses.html

Function인터페이스를 사용한 enum케이스 별 기능 구현.

Java 8 - Function Interface
참조 https://beomseok95.tistory.com/277

위를 사용해서 좀 더 나은 where조건 추가를 했다.

public enum ReservationSearchType {
    REG_USER_NAME(str -> reservation.user.name.firstName.concat(" ").concat(reservation.user.name.lastName).contains(str)),
    REG_USER_EMAIL(str -> reservation.user.email.contains(str)),
    REG_USER_PHONE(str -> reservation.user.phoneNumber.phoneNumber.contains(str));

    private Function<String, BooleanExpression> expression;

    ReservationSearchType(Function<String,BooleanExpression> expression){this.expression = expression;}

    public BooleanExpression getEq(String keyWord){
        return expression.apply(keyWord);
    }
}

각 Enum 케이스에는 Function 인터페이스의 구현부가 명시 되어있다.
들어오는 케이스별 키워드를 어느 where 조건을 추가 할지에 대해 적어두면 되겠다.

위를 사용한 QueryDsl 변화

public Page<Reservation> searchAll(ReservationSearchDto search, Pageable pageable){
        QueryResults<Reservation> result = queryFactory
                .selectFrom(reservation)
                .where(
                        eqCity(search.getCityCode()), 
                        eqKeyWord(search.getSearchType(),search.getKeyWord())
                )
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetchResults();
        return new PageImpl<>(result.getResults(),pageable,result.getTotal());
    }
    
private BooleanExpression eqKeyWord(ReservationSearchType searchType, String keyWord){
        if(StringUtils.isBlank(keyWord)) {
            return null;
        }

        return searchType.getEq(keyWord);
    }

where 조건 추가를 위임 받은 SearchType이 알아서 검색 조건을 적용하도록 되었다.

내일은 결전의 날..

좋은 일이 생겼으면 흐엉흐엉

profile
Beyond the same routine
post-custom-banner

1개의 댓글

comment-user-thumbnail
2022년 9월 23일

감사합니다

답글 달기