ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Querydsl의 동적 쿼리
    JPA/Querydsl 2023. 8. 13. 15:26

    동적 쿼리를 해결하는 방법

    • BooleanBuilder
    • Where 다중 파라미터 사용

     

     

    1. BooleanBuilder

    private List<Member> searchMember1(String usernameCond, Integer ageCond) {
    
        BooleanBuilder builder = new BooleanBuilder();
    
        if(usernameCond != null) {
            builder.and(member.username.eq(usernameCond));
        }
    
        if (ageCond != null) {
            builder.and(member.age.eq(ageCond));
        }
    
        return queryFactory
                .selectFrom(member)
                .where(builder)
                .fetch();
    }

    BooleanBuilder를 생성해서 builder에 조건을 걸어둔다. 위에서는 username이나 age가 null이 아닐 때 그와 같은 조건만 select하는 쿼리를 만들어서 반환을 해줬다.

     

     

    @Test
    public void dynamicQuery_BooleanBuilder() {
        String usernameParam = "member1";
        Integer ageParam = 10;
    
        List<Member> result = searchMember1(usernameParam, ageParam);
        assertThat(result.size()).isEqualTo(1);
    }

    테스트에서 searchMember1()을 사용한 결과 member1이라는 회원 한 명만 조회했다. usernameParam과 ageParam을 사용자에게 입력받게 하면 웹 상에서 검색을 할 수 있을 것이다.

     

     

    초기값 넣기

    BooleanBuilder builder = new BooleanBuilder(member.username.eq(usernameCond));

    생성자를 만들 때 이렇게 넣어주면 username은 무조건 넣어야한다는 규칙을 만드는 것이다.

     

     

     

     

     

     

    2. Where 다중 파라미터 사용

    private List<Member> searchMember2(String usernameCond, Integer ageCond) {
        return queryFactory
                .selectFrom(member)
                .where(usernameEq(usernameCond), ageEq(ageCond))
                .fetch();
    }

    where문에서 쿼리의 조건을 다 끝내는 것이다. 이 때에는 where문에 있는 메서드들을 정의해줘야 한다.

     

    private Predicate usernameEq(String usernameCond) {
        if (usernameCond == null) {
            return null; // null을 반환하면 where절이 null이라 무시되어서 name에 조건을 걸지 않음
        }
        return member.username.eq(usernameCond);
    }
    
    private Predicate ageEq(Integer ageCond) {
        return ageCond != null ? member.age.eq(ageCond) : null; // 삼항 연산자 사용
    }

    조건에 해당하는 값들이 null이면 where절에 member.age.eq(ageCond)와 같은 식으로 조건을 걸어주고 아니면 null을 반환한다.

    이름의 조건이 null이어서 null을 반환한다고 가정하자 Querydsl의 쿼리의 where절에서는 where(null, member.age.eq(ageCond)가 될 것인데 null이 들어가면 조건을 걸지 않으므로 이름으로는 조건을 걸지 않고 나이로만 select를 하는 것이다.

     

     

     

    @Test
    public void dynamicQuery_WhereParam() {
        String usernameParam = "member1";
        Integer ageParam = 10;
    
        List<Member> result = searchMember2(usernameParam, ageParam);
        assertThat(result.size()).isEqualTo(1);
    }

    테스트는 1번 방식과 동일한 코드이다. 메서드만 searchMember2()로 변경해주었다.

     

     

     

     

    조건 묶어서도 가능

    private List<Member> searchMember2(String usernameCond, Integer ageCond) {
        return queryFactory
                .selectFrom(member)
                .where(allEq(usernameCond, ageCond))
                .fetch();
    }
    
    private BooleanExpression usernameEq(String usernameCond) {
        return usernameCond != null ? member.username.eq(usernameCond) : null;
    }
    
    private BooleanExpression ageEq(Integer ageCond) {
        return ageCond != null ? member.age.eq(ageCond) : null;
    }
    
    private BooleanExpression allEq(String usernameCond, Integer ageCond) {
        return usernameEq(usernameCond).and(ageEq(ageCond));
    }

    이럴 때에는 BooleanExperssion으로 반환값을 바꿔줘야하며 null 처리를 특별히 신경써 줘야한다.

     

     

     

     

    Querydsl을 사용하면 자바 코드로 쿼리를 날리는 것이기 때문에 동적 쿼리를 작성할 때 훨씬 편리해진다. 또한 2번째 방식으로 했을 때에는 조건들을 따로 메서드로 빼놓기 때문에 재사용할 때도 훨씬 편하다는 장점이 있다.

    'JPA > Querydsl' 카테고리의 다른 글

    Querydls 동적 쿼리 활용  (0) 2023.08.13
    Querydsl의 수정, 삭제 쿼리  (0) 2023.08.13
    Dto로 프로젝션 결과 반환  (0) 2023.08.13
    Querydsl - Case 문  (0) 2023.08.13
    Querydsl - 서브 쿼리  (0) 2023.08.13
Designed by Tistory.