QueryDSL

[QueryDSL] 수정, 삭제 벌크 연산, SQL function 호출

쌈뽕코딩 2025. 2. 19. 21:26

수정, 삭제 벌크 연산

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

@Test
public void bulkUpdate() {
    long count = queryFactory
            .update(member)
            .set(member.username, "비회원")
            .where(member.age.lt(28))
            .execute();
    Assertions.assertThat(count).isEqualTo(2);
}

 

2. 기존 숫자에 1 더하기, 곱하기

@Test
public void bulkAdd() {
    long count = queryFactory
            .update(member)
            .set(member.age, member.age.add(1))
            // .set(member.age, member.age.multiply(2))
            .execute();
}
  • 곱하기: multiply(x)

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

@Test
public void bulkDelete() {
    long count = queryFactory
            .delete(member)
            .where(member.age.gt(18))
            .execute();
}

 

주의: JPQL 배치와 마찬가지로, 영속성 컨텍스트에 있는 엔티티를 무시하고 실행되기 때문에 배치 쿼리를 실행하고 나면 영속성 컨텍스트를 초기화 하는 것이 안전하다. 즉, 배치 쿼리를 실행하고 나면 영속성 컨텍스트의 데이터 상태와 DB에 있는 데이터 상태가 달라져 있다. (em.flush → em.clear)

SQL function 호출하기

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

// member M으로 변경하는 replace 함수 사용
@Test
public void sqlFunction() {
    List<String> result = queryFactory
            .select(Expressions.stringTemplate(
                    "function('replace', {0}, {1}, {2})",
                    member.username, "member", "M"))
            .from(member)
            .fetch();

    for (String s : result) {
        System.out.println("s = " + s);
    }
}
// 소문자로 변경해서 비교해라
@Test
public void sqlFunction2() {
    List<String> result = queryFactory
            .select(member.username)
            .from(member)
            .where(
                    member.username.eq(
                            Expressions.stringTemplate(
                                    "function('lower', {0})",
                                    member.username)
                    )
            )
            .fetch();
    for (String s : result) {
        System.out.println("s = " + s);
    }

}

 

lower 같은 ansi 표준 함수들은 querydsl이 상당부분 내장하고 있다. 따라서 다음과 같이 처리해도 결과는 같다.

.where(member.username.eq(member.username.lower()))