@Modifying(clearAutomatically = true) //벌크연산 후 영속성 컨텍스트 초기화 필요
@Query(value = "update Member m set m.age = m.age + 1 where m.age >= :age")
int bulkAgePlus(@Param("age") int age);
@Test
public 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 resultCnt = memberRepository.bulkAgePlus(20);
// em.clear();
//벌크쿼리는 영속성 컨텍스트에 올리지 않고 DB에 바로 처리 하므로 같은 트랜잭션 안에서 불일치가 발생
//따라서 벌크연산 후에는 반드시 영속성 컨텍스트를 초기화!!!
List<Member> res = memberRepository.findByUsername("member5");
Member member5 = res.get(0);
System.out.println("member5 = " + member5);
//then
assertThat(resultCnt).isEqualTo(3);
}
📌 벌크성 쿼리 실행 후 영속성 컨텍스트 초기화
- @Modifying(clearAutomatically = true) 어노테이션 옵션 적용
- false가 기본값임
- 벌크연산 뒤에 해당값을 다시 조회하는 등의 추가행위가 있을 경우에는 반드시 영속성 컨텍스트 초기화!
- 벌크연산은 영속성 컨텍스트를 무시하고 실행하므로, 영속성 컨텍스트에 올려져있는 엔티티의 상태와 벌크연산 뒤 DB에 저장된 엔티티 상태가 달라질 수 있음
- 권장하는 방안
- (1) 영속성 컨텍스트에 엔티티가 없는 상태에서 벌크 연산을 먼저 실행
- (2) 부득이 영속성 컨텍스트에 엔티티가 있을 경우 벌크 연산 직후 영속성 컨텍스트 초기화