벌크 업데이트 주의 사항

MinSeong Kang·2022년 8월 18일
0

spring

목록 보기
12/18

JPA에서는 보통 데이터를 변경할 때, 데이터를 영속성 컨텍스트에 가져와 setter 메서드를 통해 변경하면 변경 감지를 통해 DB에 업데이트 쿼리를 수행한다.

만약 한 개의 데이터가 아닌 여러개의 데이터를 변경해야할 때, 모든 데이터를 영속성 컨텍스트로 가져와 데이터 갯수에 맞게 setter 메서드를 통해 변경할 수 있다.

Member member1 = new Member("member1", "silver");
Member member2 = new Member("member2", "silver");
Member member3 = new Member("member3", "silver");
Member member4 = new Member("member4", "silver");
Member member5 = new Member("member5", "silver");

em.persist(member1);
em.persist(member2);
em.persist(member3);
em.persist(member4);
em.persist(member5);

em.flush();
em.clear();

다음과 같이 데이터베이스에 등급이 silver인 멤버가 5개가 저장되어 있다.


변경감지를 통한 여러 데이터 변경

// 트랜잭션 시작
 Member findMember1 = em.find(Member.class, 1L);
 Member findMember2 = em.find(Member.class, 2L);
 Member findMember3 = em.find(Member.class, 3L);
 Member findMember4 = em.find(Member.class, 4L);
 Member findMember5 = em.find(Member.class, 5L);
 
 findMember1.setRank("gold");
 findMember2.setRank("gold");
 findMember3.setRank("gold");
 findMember4.setRank("gold");
 findMember5.setRank("gold");
 // 트랜잭션 커밋
다음과 같이 5개의 데이터 모두를 영속성 컨텍스트로 가져온 다음에 변경감지를 통해 트**랜잭션이 커밋되는 시점에 데이터를 변경**할 수 있다.

5개의 데이터를 변경하기 위해 각 데이터마다

  • 영속성 컨텍스트로 가져오는 코드 (em.find)
  • setter 메서드를 통해 변경하는 코드 (setXX)

2줄의 코드가 필요하다.
또한 각 데이터의 변경감지에 따른 update 쿼리가 각각 날라가 총 5개의 쿼리가 필요하다.

하지만 만약 데이터가 5개가 아닌 더 많은 데이터를 변경해야 할때 더 많은 코드가 요구될 것이며, 변경하려는 데이터의 개수만큼 update 쿼리가 나타날 것이다. 비효율적인 방법이다.!


벌크 업데이트를 통한 여러 데이터 변경

벌크 업데이트란 단건 UPDATE, DELETE가 아닌 다건의 UPDATE, DELETE 연산을 하나의 쿼리로 하는 것을 말한다.

em.createQuery("update Member m set m.rank = 'gold'")
	.executeUpdate();

다음과 같이 JPQL를 통해 한방에 모든 멤버 데이터의 등급을 gold로 변경할 수 있다.
코드도 간단할 뿐만 아니라 단 하나의 update 쿼리로 데이터를 변경할 수 있어, 이전 방법보단 성능상 효율적이다.

하지만 벌크 업데이트 사용시 주의해야할 점이 있다.


벌크 업데이트 사용시 주의해야할 점

  • 벌크 업데이트는 영속성 컨텍스트를 지나치지 않고 바로 데이터베이스에 쿼리문을 보낸다.
  • 벌크 업데이트 실행시 바로 데이터베이스에 반영되지만, 만약 영속성 컨텍스트에 있는 데이터에는 해당 변경사항에 반영되지 못한 상태일 것이다.
  • 따라서 영속성 컨텍스트에 데이터를 올리기 전에 벌크 업데이트를 실행시키거나, 벌크 업데이트를 실행시 영속성 컨텍스트를 clear 시킨 이후 데이터 사용시 다시 데이터베이스를 통해 영속성 컨텍스트로 가져오게 끔 한다.

Spring Data Jpa

@Modifying
@Query("Update Member m set m.rank = 'gold'")
int updateRant();

spring data jpa 에서는 @Query를 통해 직접 JPQL문을 작성할 수 있는데, 해당 예시 JPQL문은 벌크 업데이트 쿼리이다. 따라서 @Modifying을 꼭 써줘야하는데, 이는 해당 쿼리 메서드 실행 직후 바로 영속성 컨텍스트를 clear하는 기능을 한다. 따라서 영속성 컨텍스트의 1차 캐시와 관련한 문제를 해결할 수 있다.

벌크 업데이트 사용시, 영속성 컨텍스트를 꼭 클리어하거나 영속성 컨텍스트에 데이터가 없을 때 실행시켜야 한다.


참고문헌

https://www.inflearn.com/course/ORM-JPA-Basic/dashboard
https://www.baeldung.com/spring-data-jpa-modifying-annotation

0개의 댓글