Jpa 벌크 연산 주의점

JWJ·2024년 5월 3일

jpa

목록 보기
10/11

벌크 연산이란 한번에 대량의 데이터를 수정하는 것을 뜻한다. Jpa는 영속성 컨텍스트라는 개념이 존재하기 때문에 벌크 연산 시 주의점이 있다. 아래 예제를 통해서 주의점을 살펴보자.

1. 벌크 연산 코드

    @Modifying
    @Query("update Member m set m.age = m.age + 1 where m.age >= :age")
    int bulkAgePlus(@Param("age") int age);
  • spring data jpa의 코드로 특정 나이보다 많다면 모든 Member 에 대해서 나이를 1증가하는 벌크 연산이다.

2. 테스트 코드

    @Test
    void bulkUpdate() {

        //given
        memberRepository.save(new Member("member1", 10));
        memberRepository.save(new Member("member2", 19));
        memberRepository.save(new Member("member3", 20));
        memberRepository.save(new Member("member4", 21));
        memberRepository.save(new Member("member5", 40));

        //when
        int resultCount = memberRepository.bulkAgePlus(20); //벌크 연산
        Member member5 = memberRepository.findMemberByUsername("member5");
        System.out.println("member5 = " + member5);

        //then
        ...
    }
  • memberRepository.bulkAgePlus(20) 를 통해서 나이가 20살 이상인 member3,4,5 는 나이가 1씩 증가하게 된다. 그러면 member5 는 나이가 41이 나오는 것을 기대할 수 있다.
  • 하지만 기대와는 다르게 실행 결과는 다음과 같다. member5 = Member(username=member5, age=40)
  • 벌크 연산을 통해서 디비에는 내용이 업데이트 됐지만, 영속성 컨텍스트에는 내용이 업데이트 되지 않았기 때문이다. 그래서 @Modifying(clearAutomatically = true) 옵션을 사용하면 쿼리를 날린 후, em.clear() 를 시켜줘서 우리가 기대했던 결과를 확인할 수 있을 것이다. (영속성 컨텍스트가 업데이트 됐기 때문)
    @Modifying(clearAutomatically = true)
    @Query("update Member m set m.age = m.age + 1 where m.age >= :age")
    int bulkAgePlus(@Param("age") int age);
  • 동일한 테스트 코드 실행결과: member5 = Member(username=member5, age=41)

따라서 Jpa에서 벌크 연산후 추가 로직이 있을 경우 영속성 컨텍스트를 업데이트 해주도록 하자.

profile
인사이트를 얻고 정리하는 공간입니다

0개의 댓글