QueryDSL 동적 쿼리를 작성하는 방법에 대해 알아보자.

반응형

QueryDSL을 사용하는 이유는 아마 동적 쿼리를 아주 쉽게 해결할 수 있어서가 아닐까 싶다.

이번 포스팅에서는 QueryDSL을 사용해서 동적 쿼리를 작성하는 방법에 대해 포스팅해 보려한다.

 

QueryDSL 설정, 사용방법, 문법에 대해 알고 싶다면 아래 링크를 통해 확인할 수 있다.

2023.07.10 - [오픈소스] - QueryDSL 기본 문법 총정리

2023.06.27 - [오픈소스] - [QueryDSL] 스프링부트 3.x 버전에서 QueryDSL 설정하기

2023.07.10 - [오픈소스] - QueryDSL 사용법, DTO 반환 방법 정리

 


동적 쿼리

querydsl에서 동적 쿼리를 사용하는 방법 중 Where 절에서 다중 파라미터를 사용하는 방법에 대해 설명하려 한다.

이 방법은 where절 안에 들어갈 boolean 값을 파라미터에 따라 메서드로 추출하여 만드는 방법이다.

각각의 조건들을 메서드로 작성하였기 때문에조합하고, 재사용할 수 있다는 장점이 있다.

 

먼저 이번 포스팅에서 설명하기 위해 사용할 테스트 코드를 보면 다음과 같다.

    @Test
    public void 동적쿼리 throws Exception {
        String usernameParam = "member1";
        Integer ageParam = 10;
        
        List<Member> result = queryFactory
            .selectFrom(member)
            .where(usernameEq(usernameParam), ageEq(ageParam))
            .fetch();
            
        Assertions.assertThat(result.size()).isEqualTo(1);
    }

이제 이 코드의 where()절에 들어가 있는 메서드를 작성해보자.

작성하는 메서드의 반환 타입은 QueryDSL의  BooleanExpression 를 반환하도록 작성하면 된다.

 

파라미터로 받은 값이 null이 아니면 파라미터 값과 같은 username을 반환, null이면 null 반환

문자열의 경우 "" 같은 빈 문자도 입력될 수 있기 때문에 StringUtils의 hasText()로 값을 체크 하였다.

    private BooleanExpression usernameEq(String usernameParam) {
    	return StringUtils.hasText(usernameParam) ? member.username.eq(usernameParam) : null;
    }

 

파라미터로 받은 값이 null이 아니면 파라미터 값과 같은 age를 반환, null이면 null 반환
    private BooleanExpression ageEq(Integer ageParam) {
    	return ageParam != null ? member.age.eq(ageParam) : null;
    }

 

이제 해당 테스트 코드를 실행하면 이름이 "member1"이고 나이가 "10"인 회원을 반환하게 된다.

 

null 무시

queryFactory의 where절에서 null이 들어가면 자동으로 null을 무시한다.

만약 usernameEq() 메서드에 해당하는 결과가 없어서 null이 반환된다면 다음과 같이 될 것이다.

    return queryFactory
        .selectFrom(member)
        .where(null, ageEq(ageParam))
        .fetch();

이 경우에는 null을 무시하므로 ageEq()조건만 확인하여 member를 조회한다.

만약 where 절의 두 메서드가 결과가 둘다 null이라면 where절이 없는 것으로 간주되고 모든 member를 조회한다.

 

 

메서드 조합

아래처럼 위에서 작성한 두 메서드들을 조합하여 만들 수 있다.

    private BooleanExpression allEq(String usernameParam, Integer ageParam){
        return usernameEq(usernameParam).and(ageEq(ageParam));
    }