DB에 update 쿼리 1번으로 엔티티의 모든 요소를 수정하는것을 벌크성 수정 쿼리라 한다.
쿼리가 적용되는 요소가 2개이상인 경우를 말한다,
순수 JPA에서의 벌크 연산
Repository
public int bulkAgePlus(int age){
return em.createQuery(
"update Member m set m.age = m.age +1" +
" where m.age >= :age")
.setParameter("age" , age)
.excuteUpdate()
//excuteUpdate는 최종적으로 연산이 적용된 데이터의 갯수가 나온다.
}
데이터 JPA 벌크연산
Repository
@Modifying //update 시엔 이 값을 꼭 넣어야 한다, 없으면 에러가 발생
@Query(update Member m set m.age = m.age +1 where m.age >= :age)
int bulkAgePlus(@Param ("age") int age)
벌크연산에는 문제가 있는데
JPA는 영속성 컨테이너에서 엔티티들을 관리하고 있는데
이때 벌크여산은 영속성을 무시하고 DB에 바로 쿼리를 적용시켜버린다.
그럼 영속화 되기 전 Data와 영속성 관리중인 데이터간에 불일치가 발생할 수 있다.
만약
int resultCount = memberRepository.bulkAgePlus(20);
//DB에 벌크연산을 진행
List<Member> result = memberRepository.findByUsername("member5")
Member member5 = result.get(0)
//그런데 find는 영속성 에서 값을 찾아온다.
위 벌크연산이 적용된건DB 뿐이라 영속성엔 벌크연산이 적용되지 않은 데이터가 반환된다.
그래서 해결법은
1.같은 @Transaction 인 service 에서
2.@Persistence Context
EntityManager entityManager 영속성 컨테이너를 호출
3.벌크 연산이 실행된 후 영속성 컨테이너를 비워준다.
int resultCount = memberRepository.bulkAgePlus(20);
entityManager.clear()
entityManager.flush()
//벌크연산 후 영속성 컨테이너를 초기화 해준다.
4.find때 영속성에 값이 없어서 DB 에서 값을 가져온다.
JPA에선 Update후 flush 후 실행해야 한다.
데이터 JPA에서는 em.clear()할 필요가 없다 ,
Repository에서
@Modifying(clearautomatically = true)
// 이 옵션이 있으면 벌크연산후 자동으로 em.clear를 해준다.
@Query("update Member m set m.age = m.age +1 where m.age >= :age")
int bulkAgePlus(@Param ("age") int age)
'Spring Data JPA' 카테고리의 다른 글
| 3월 22일 SpringDataJPA hint & lock (0) | 2023.03.22 |
|---|---|
| 3월 22일 SpringDataJPA EntityGraph (fetch Join) (0) | 2023.03.22 |
| 3월 22일 SpringDataJPA 페이징과 정렬 (0) | 2023.03.22 |
| 3월 21일 SpringDataJPA 반환타입 (0) | 2023.03.21 |
| 3월 21일 SpringDataJPA 리포지토리에 메소드 구현 (0) | 2023.03.21 |