벌크성 수정쿼리

JIWOO YUN·2023년 10월 17일
0

SpringDataJPA

목록 보기
3/4
post-custom-banner

벌크성 수정 쿼리

  • JPA는 기본적으로 값을 변경시 Commit 시점에 더티 체킹을 통해서 한건씩 처리함.

만약 전 직원의 월급을 10프로 인상하는 경우 한건씩 처리하는 것보다 DB에 update쿼리를 한번에 하는게 효율적임 -> 이런것을 JPA에서 벌크성 수정 쿼리 라고함.

순수 JPA를 사용한 수정 쿼리

  1. 회원의 나이를 전부 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;
}

CreateQuery를 update set을 날려줌. + executeUpdate()를 넣어줘야함.

executeUpdate()

  • select 구문을 제외한 다른 구문을 수행할때 사용되는 함수.
  • 반환 값 --> insert/delete/update 구문은 반영된 레코그 건수 반환
  • create/ drop은 -1 반환

스프링 데이터 JPA 사용 수정 쿼리

@Modifying 을 넣어주는 이유

  • Query 어노테이션을 통해서 작성된 Insert/Update/Delete 쿼리에서 사용되는 어노테이션

JPA에서 bulk성 update의 문제

  • JPA에서는 데이터의 변경이 일어날 때는 영속성 컨텍스트 안에서 실행되어야하지만 벌크성 업데이트의 경우 이걸 무시하고 DB에 때려넣는다. -> 데이터의 싱크가 맞지 않는 문제가 발생할 수있다.
    @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살로 나오게 된다.

profile
열심히하자
post-custom-banner

0개의 댓글