만약 전 직원의 월급을 10프로 인상하는 경우 한건씩 처리하는 것보다 DB에 update쿼리를 한번에 하는게 효율적임 -> 이런것을 JPA에서 벌크성 수정 쿼리
라고함.
public int bulkAgePlus(int age){
int resultCount = em.createQuery(
"update Member m set m.age = m.age + 1" +
"where m.age >= :age")
.setParameter("age",age)
.executeUpdate();
return resultCount;
}
CreateQuery를 update set을 날려줌. + executeUpdate()를 넣어줘야함.
executeUpdate()
JPA에서 bulk성 update의 문제
@Test
public void bulk() throws Exception{
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));
int result = memberRepository.bulkAgePlus(20);
List<Member> member5 = memberRepository.findByUsername("member5");
assertThat(result).isEqualTo(3);
}
여기서 member5를 찾아서 찍어보면 나이가 40으로 찍힌다. -> 영속성 컨텍스트를 무시하고 DB를 변화시키기 때문에 영속성에는 그냥 40살로 남아있는 것이다.
-> 이 문제를 해결할려면 bulk를 진행했을때 영속성 컨텍스트를 날려버리는 방법이 있다.
@Test
public void bulk() throws Exception{
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));
int result = memberRepository.bulkAgePlus(20);
//벌크 연산 이후 flush를 통해서 변경되지 않는 것도 전부 적용
//그다음 clear를 통해서 영속성 컨텍스트를 완전히 제거해줌.
em.flush();
em.clear();
List<Member> member5 = memberRepository.findByUsername("member5");
assertThat(result).isEqualTo(3);
}
@Modifying(clearAutomatically = true)
@Query("update Member m set m.age = m.age + 1 where m.age >= :age")
int bulkAgePlus(@Param("age")int age);
em.flush와 em.clear를 해결해주는 걸 Modifying에 clearAutomatically = true 로 해줄 경우 bulk 가 진행되고 영속성 컨텍스트를 자동으로 날려주기 때문에 bulk를 진행하고 조회하게 된다해도 41살로 나오게 된다.