[QueryDSL] 중급 문법3

윤경·2021년 12월 9일
0

QueryDSL

목록 보기
8/11
post-thumbnail

[6] 수정, 삭제 벌크 연산

    @Test
    @Commit
    public void bulkUpdate() {

        // member1 = 10 -> 비회원
        // member2 = 20 -> 비회원
        // member3 = 30 -> 유지
        // member4 = 40 -> 유지

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

h2➡️ 이렇게 10, 20살 회원은 비회원으로 바뀐 것을 확인 할 수 있다.

  • @Commit: 해주지 않으면 롤백해버리기 때문에 H2에서 이렇게 결과를 확인할 수 없다.

⚠️ 영속성 컨텍스트가 항상 우선권을 가진다.

(벌크 연산은 영속성 컨텍스트를 무시하고 DB에 바로 쿼리를 날림)

(= DB의 상태와 영속성 컨텍스트의 상태가 달라져버림)

영속성 컨텍스트에는

member1 -> member1
member2 -> member2
member3 -> member3
member4 -> member4
여전히 이렇게 남아있고

DB에는

member1 -> 비회원
member2 -> 비회원
member3 -> member3
member4 -> member4
변경되어 이렇게 남아있을 것.

그런데 이렇게 상태가 다른 상황에서 select를 또 한다면 어떤 내용을 가져올까?

DB의 내용은 무시하고 영속성 컨텍스트의 내용인 member1~4를 username으로 가져오게 된다.

➡️ 이렇게 벌크 연산 후 select해 출력 결과를 확인하면 영속성 컨텍스트의 내용을 출력시키는 것을 볼 수 있다.

그럼 어떻게 해야할까?

em.flush();
em.clear();

그냥 영속성 컨텍스트에 있는걸 flush 해버리고 영속성 컨텍스트를 clear 해주자.

다양한 연산과 삭제

    @Test
    public void bulkAdd() {
        long count = queryFactory
                .update(member)
                // add말고 따로 minus는 없음. add(-1)로 쓰면 됨.
                // 곱하기는 multiply
                .set(member.age, member.age.add(1))
                .execute();
    }

    @Test
    public void bulkDelete() {
        queryFactory
                .delete(member)
                .where(member.age.gt(18))   // 18살 이상은 삭제
                .execute();
    }

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


[7] SQL function 호출하기

SQL function은 JPA와 같이 Dialect데 등록된 내용만 호출할 수 있다.

replace 함수

    @Test
    public void sqlFunction() {
        // 멤버의 이름을 모두 M으로 바꾸기
        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);
        }
    }

lower 함수

    @Test
    public void sqlFunction2() {
        List<String> result = queryFactory
                .select(member.username)
                .from(member)
//                .where(member.username.eq(
//                        Expressions.stringTemplate("function('lower', {0})", member.username)))
                .where(member.username.eq(member.username.lower()))
                .fetch();

        for (String s : result) {
            System.out.println("s = " + s);
        }
    }
  • lower 같은 ansi 표준 함수들은 querydsl이 상당부분 내장하고 있다. 따라서 위 코드와 같이 처리해도 같은 결과를 얻을 수 있다.

profile
개발 바보 이사 중

0개의 댓글