10. 벌크성 수정 쿼리

민정·2022년 12월 12일
0

Spring Data JPA

목록 보기
10/17
post-thumbnail

✏️ JPA의 수정

JPA는 엔티티를 조회한 뒤, commit 시점에 더티체킹을 통해 수정된 값이 있다면 update 쿼리를 날린다.

즉, 엔티티 하나 하나 더티체킹해서 update를 각각 날린다.

✏️ 벌크성 수정 쿼리

하지만, "모든 직원의 연봉을 10%씩 인상해라"라는 식으로 많은 데이터를 변경해야하는 경우

=> 엔티티를 하나씩 조회해서 더티체킹을 통해 update를 하기보다는 DB에 한 번의 update 쿼리를 날리는 것이 효과적



✨ 순수 JPA - 벌크성 수정 쿼리

  • exeuteUpdate
    • 반환 값 : update된 행의 개수

📁 MemberJpaRepository

회원 중 특정 나이 이상인 사람의 나이를 모두 +1 하여라

    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;
    }


✨ Spring Data JPA - 벌크성 수정 쿼리

int = 반환 타입
@Modifying : JPA의 executeUpdate를 실행
clearAutomatically = true : 벌크 연산 이후에 em.clear()자동으로 해줌

📁 MemberRepository

    @Modifying(clearAutomatically = true)
    @Query("update Member m set m.age = m.age + 1 where m.age >= :age")
    int bulkAgePlus(@Param("age") int age);
    // @Modifying: JPA의 executeUpdate를 실행 - 작성 안하면 getResultList, getSingleResult호출함
    // clearAutomatically = true: 벌크 연산 이후에 em.clear()자동으로 해줌


🚨 JPA에서 벌크성 수정 쿼리 유의사항

🔴 문제점

JPA는 영속성 컨텍스트라는 것이 있어서 Entity가 모두 관리된다.

벌크 연산은 영속성 컨텍스트를 무시하고 바로 쿼리를 DB에 날려버린다.

⇒ 서로 안맞을 수 있다.
영속성 컨텍스트에 있는 Entity의 정보 != DB에 있는 해당 Entity의 정보

DB에 있는 값은 update된 후의 값이고, 영속성 컨텍스트에는 update되기 전의 값이 있을 것이기 때문이다.

🟢 해결책

즉, 벌크 연산 이후에는 영속성 컨텍스트를 반드시 초기화(em.flush(), em.clear())시켜야한다.

초기화 시킨 뒤, 다시 엔티티를 DB에서 조회해서 영속성 컨텍스트에 담아야한다.

참고

JPQL은 쿼리 실행 전영속성 컨텍스트 flush 시킨 뒤 실행함.

=> JPQL은 영속성 컨텍스트에 있는 데이터를 고려하지 않고 DB에서 데이터를 조회해오기 때문!

=> 조회하기 전에 영속성 컨텍스트의 정보를 DB와 동기화 시켜준 뒤 값을 가져오기 위해서 JPQL 실행전에 flush를 시킨다.



출처

김영한 강사님 - 인프런 실전! 스프링 데이터 JPA

0개의 댓글