Querydsl - 벌크연산, SQL Function

HotFried·2024년 2월 26일
0

Querydsl

목록 보기
9/9

벌크연산

데이터를 개별로 수정하는 것 보다 한번에 수정하는 것이 훨씬 효율적이다.

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

위와 같이 update set문을 활용해 벌크연산을 진행하면 된다.


♨ 주의!!!

주의!

앞선 포스팅들에서도 벌크연산에 대한 주의점이 적혀있을 것이다.
다시 한번 복기해보자.

1. 현재 엔티티들은 영속성 컨텍스트에 영속된 상태이다.
2. 벌크 연산을 하면 영속성 컨텍스트를 무시하고 DB에 바로 쿼리를 내보낸다.
-> 영속성 컨텍스트와 DB의 정보가 다르다.
3. 이후 우리가 해당 엔티티를 조회하려고 하면 JPA는 DB에 있는 데이터를 가져온다.
-> 하지만 영속성 컨텍스트에 id가 존재하기 때문에 DB에서 가져온 데이터를 날려버린다.

결과적으로 벌크연산을 통해 DB에 저장된 정보와, 영속성 컨텍스트에 존재하는 정보가 다른 결과가 발생한다.

따라서 벌크연산 이후에는 반드시 em.flush(), em.clear()를 통해 영속성 컨텍스트를 초기화 해주고
DB에서 데이터를 가져오도록 한다.


아래의 예시처럼 flush(), clear()를 통해 영속성 컨텍스트를 초기화 해주고 데이터를 조회하는 것이 바람직하다.

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

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

        List<Member> result = queryFactory
                .selectFrom(member)
                .fetch();

        for (Member m : result) {
            System.out.println("m = " + member1);
        }
    }

add, multiply, divide, sqrt...

다양한 메소드가 지원이 된다.
하지만, minus의 경우 존재하지 않기 때문에 add(-1)과 같이 음수를 더해주도록 하자.

@Test
    void bulkUpdate() {
        long count = queryFactory
                .update(member)
                .set(member.age, member.age.add(1))
                .execute();
    }

삭제

delete 메소드를 이용해 데이터를 삭제해주면 된다.

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

SQL Function

만약 해당 SQL Function이 JPA의 DB방언에 존재한다면 호출해서 이용할 수 있다.

예제1 - replace

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

예제2 - lower

@Test
    void sqlFunction() {
        String result = queryFactory
                .select(member.username)
                .from(member)
                .where(member.username.eq(
                        Expressions.stringTemplate("function('lower', {0})",
                                member.username)))
                .from(member)
                .fetchFirst();
    }

위 예제들과 같이 SQL Function을 호출해서 간단하게 이용하면 된다.
어려운게 없습니다.


참고 :

실전! Querydsl

profile
꾸준하게

0개의 댓글