Java / / 2023. 1. 14. 08:25

[JPA] 동적 쿼리 - BooleanBuilder 사용

반응형

해당 글은 김영한 님의 querydsl을 수강하며 정리하려고 적는 포스팅입니다.

 

서론

JPA를 사용하다 보면 동적 쿼리를 작성해야 할 때가 있다.

querydsl은 동적 쿼리를 해결하는 두 가지 방식을 제공하고 있다.

 

동적 쿼리를 해결하는 두 가지 방식

  1. BooleanBuilder
  2. Where 다중 파라미터 사용

 

1. BooleanBuilder

@Test
public void dynamicQuery_BooleanBuilder() {
    String usernameParam = "member1";
    Integer ageParam = null;

    List<Member> result = searchMember1(usernameParam, ageParam);

    assertThat(result.size()).isEqualTo(1);
}

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();
}

---------------------------------------------------------------------------
2023-01-13T16:23:09.451+09:00 DEBUG 17488 --- [           main] org.hibernate.SQL                        : 
    /* select
        member1 
    from
        Member member1 
    where
        member1.username = ?1 */ select
            m1_0.member_id,
            m1_0.age,
            m1_0.team_id,
            m1_0.username 
        from
            member m1_0 
        where
            m1_0.username=?

값이 필수로 넘어 온다고 가정한다면 아래처럼 BooleanBuilder의 생성자에 필수 param을 넣어주면 된다.

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

 

2. Where 다중 파라미터 사용

@Test
public void dynamicQuery_WhereParam() {
    String usernameParam = "member1";
    Integer ageParam = null;

    List<Member> result = searchMember2(usernameParam, ageParam);

    assertThat(result.size()).isEqualTo(1);
}

private List<Member> searchMember2(String usernameCond, Integer ageCond) {
    return queryFactory
            .selectFrom(member)
            .where(usernameEq(usernameCond), ageEq(ageCond))
            //.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));
}
  • where 조건에 응답 값으로 null이 들어가면 무시한다. (동적 쿼리가 만들어진다.)
  • 메서드를 다른 쿼리에도 재활용 가능하다.
  • 쿼리 자체의 가독성이 높아져서 1번 방법인 BooleanBuilder 보다 좋다
  • 조합도 가능하다

 

조합 가능

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


//   조합 예시 - 광고 상태 isValid, 날자가 In  => isServicable라는 서비스 생성

//    private BooleanExpression isServicable(String usernameCond, Integer ageCond) {
//        return isValid(usernameCond).and(DateBwtweenIn(ageCond));
//    }
  • 대신 null 체크는 주의해서 처리해 주어야 한다.
  • BooleanExpression로 타입을 사용해야 조합이 가능하다.
  • Predicate 타입으로 사용하면 조합이 불가능하다.
반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유