[QueryDSL] 중급 문법 ②

kiteB·2021년 12월 6일
0

QueryDSL

목록 보기
6/9
post-thumbnail

[ 동적 쿼리 - BooleanBuilder 사용 ]

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

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

BooleanBuilder 사용

@Test
public void 동적쿼리_BooleanBuilder() throws Exception {
    String usernameParam = "member1";
    Integer ageParam = 10;
    
    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();
}

BooleanBuilder를 통한 동적 쿼리 생성은 빌더를 생성 후 필요한 조건을 null 확인 여부에 따라 and 또는 or 등으로 더해주면 된다.


[ 동적 쿼리 - Where 다중 파라미터 사용 ]

Where 다중 파라미터 사용

@Test
public void 동적쿼리_WhereParam() throws Exception {
    String usernameParam = "member1";
    Integer ageParam = 10;
    
    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))
            .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;
}
  • Where 조건에 null 값은 무시된다.
  • usernameEq()와 같은 메서드를 다른 쿼리에서도 재활용할 수 있다.
  • 쿼리 자체의 가독성이 높아진다.

메서드 조합 가능

private BooleanExpression allEq(String usernameCond, Integer ageCond) {
    return usernameEq(usernameCond).and(ageEq(ageCond));
}
  • method chaining 가능
  • null 체크는 주의해서 처리해야 한다.

[ 수정, 삭제 벌크 연산 ]

1. 쿼리 한 번으로 대량 데이터 수정

long count = queryFactory
        .update(member)
        .set(member.username, "비회원")
        .where(member.age.lt(28))
        .execute();

2. 기존 숫자에 1 더하기

long count = queryFactory
        .update(member)
        .set(member.age, member.age.add(1))
        .execute();

곱하기는 multiply(x) 사용 → Ex. member.age.multiply(2)

3. 쿼리 한 번으로 대량 데이터 삭제

long count = queryFactory
        .delete(member)
        .where(member.age.gt(18))
        .execute();

🚫 주의 ❗

JPQL 배치와 마찬가지로, 영속성 컨텍스트에 있는 엔티티를 무시하고 실행되기 때문에 배치 쿼리를 실행하고 나면 영속성 컨텍스트를 초기화하는 것이 안전하다.


[ SQL function 호출하기 ]

JPA와 같이 Dialect에 등록된 내용만 호출할 수 있다.

1. replace 함수

String result = queryFactory
        .select(Expressions.stringTemplate("function('replace', {0}, {1}, {2})", member.username, "member", "M"))
        .from(member)
        .fetchFirst();

memberM으로 변경된다.


2. lower 함수

String result = queryFactory
        .select(member.username)
        .from(member)
        .where(member.username.eq(Expressions.stringTemplate("function('lower', {0})", member.username)))

lower 같은 ansi 표준 함수들은 querydsl이 대부분 내장하고 있기 때문에 다음과 같이 처리해도 결과는 같다.

.where(member.username.eq(member.username.lower()))
profile
🚧 https://coji.tistory.com/ 🏠

0개의 댓글