ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 벌크 연산
    JPA 2021. 2. 28. 18:23

    벌크 연산은 쿼리 한 번으로 대량의 데이터를 수정할 때 사용된다.

    하지만 벌크 연산을 사용할 때 주의해야 할 점이 있다.

     

    다음 쿼리를 보자

            long count = queryFactory
                    .update(member)
                    .set(member.age, member.age.add(1))
                    .execute();
            
            List<Member> result = queryFactory
                    .selectFrom(member)
                    .fetch();
            for (Member member1 : result) {
                System.out.println("member1 = " + member1);
            }

     

    모든 멤버의 나이를 1살 씩 더해주고, 멤버를 조회하였다.

     

    쿼리 사용전

    쿼리 사용후

    그런데 쿼리를 날리기 전과 후의 차이가 없다?

     

    여기가 바로 벌크 연산을 할 때 주의 해야할 점인데, 벌크 연산은 DB 데이터에 직접 접근해서 데이터를 변경해준다. 하지만 일반적으로 JPA에서 member를 조회할 때 이미 멤버가 1차캐시 즉 영속성 컨테이너에 있기 때문에 DB에서 조회하지 않고 1차 캐시에서 바로 가져온다. 

    하지만 벌크 연산은 DB 데이터만 바꿔 주기 때문에 영속성 컨테이너에는 옛날 데이터가 그대로 남아있게 된다.

     

    따라서 벌크 연산을 사용할 때는 반드시 영속성 컨테이너를 초기화 해주는 작업을 반드시 해야 한다. (em.flush()와 em.clear()사용)

     

            long count = queryFactory
                    .update(member)
                    .set(member.age, member.age.add(1))
                    .execute();
                    
            em.flush();
            em.clear();
            
            List<Member> result = queryFactory
                    .selectFrom(member)
                    .fetch();
            for (Member member1 : result) {
                System.out.println("member1 = " + member1);
            }

     

    정상적으로 멤버 나이가 조회되는 것을 알 수 있다. (참고로 Querydsl에서는 @Modifying을 사용할 수 없음 ㅠㅠ)

    'JPA' 카테고리의 다른 글

    Querydsl로 동적쿼리 쉽게 작성하기  (0) 2021.03.01
    페치 조인(fetch join)  (0) 2021.02.23
    OSIV (Open Session In View)  (0) 2021.02.22

    댓글

Designed by Tistory.