Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

Query Method, 벌크성 수정 쿼리 본문

인프런/[인프런] Spring Data JPA

Query Method, 벌크성 수정 쿼리

Seung__ 2021. 8. 29. 22:11

예를들어 모든 인원의 나이를 하나 씩 올리거나, 연봉을 올리거나 할 때,

엔티티를 하나하나 불러와서 업데이트 하는 것 보다.

DB에서 bulk로 변경하는 편이 적합하다.

 

1. JPA로 bulk 연산


  • executeUpdate()를 실행하면 업데이트, 삭데된 엔티티의 수를 반환.
 public int bulkAgePlus(int age){
        return em.createQuery("update Member m set m.age = m.age + 1 where m.age >= :age")
                    .setParameter("age", age)
                    .executeUpdate(); //Returns: the number of entities updated or deleted
    }
 public int bulkAgePlus(int age){
        return em.createQuery("update Member m set m.age = m.age + 1 where m.age >= :age")
                    .setParameter("age", age)
                    .executeUpdate(); //Returns: the number of entities updated or deleted
    }

 

 

 

2. SpringDataJpa에서 bulk 연산


  • Query는 동일함
  • @Modifying 적용 필요 : 해당 annotation이 적용되어야, jpa의 executeUpdate( )실행됨.
    없으면 ResultRist or SingleResult 반환됨.
@Modifying //얘가 있어야 jpa의 .executeUpdate()실행됨. 없으면 resultRist or SingleResult 반환.
@Query("update Member m set m.age = m.age+1 where m.age >= :age")
int bulkAgePlug(@Param("age") int age);
  @Test
    public void bulkUpdate(){
        //given
        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));

        //when
        int resultCount = memberRepository.bulkAgePlug(20);

        //then
        Assertions.assertThat(resultCount).isEqualTo(3);

    }
  • @Modyfing을 빼면???
    • InvalidDataAccessApiUsageException이 발생한다.
InvalidDataAccessApiUsageException: org.hibernate.hql.internal.QueryExecutionRequestException:
Not supported for DML operations

 

 

 

3.  JPA의 BULK 연산 문제점


  • JPA는 영속성 컨텍스트에서 엔티티를 관리한다.
  • 하지만 BULK 연산을 하면 영속성 컨텍스트를 거치지 않고 바로 DB에 반영해버린다.
  • 즉. BULK 연산 진행 후 영속성 컨텍스트와 DB에 DATA 차이가 있다.
  • 다라서 BULK 연산 수 영속성 컨텍스트를 초기화 해야 한다.
    • em.clear() -> 영속성 컨텍스트의 data 싹~ 날려버림.
 @Test
    public void bulkUpdate(){
        //given
        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));

        //when
        int resultCount = memberRepository.bulkAgePlug(20);
        em.flush();
        em.clear();
        
        //then
        Assertions.assertThat(resultCount).isEqualTo(3);

    }
  • 근데 springDataJPa에서 알아서 해줌ㅋㅋㅋㅋㅋㅋㅋ
    • @Modifying(clearAutomatically = true)
@Modifying(clearAutomatically = true) //얘가 있어야 jpa의 .executeUpdate()실행됨. 없으면 resultRist or SingleResult 반환.
@Query("update Member m set m.age = m.age+1 where m.age >= :age")
int bulkAgePlug(@Param("age") int age);
  @Test
    public void bulkUpdate(){
        //given
        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));

        //when
        int resultCount = memberRepository.bulkAgePlug(20);
        em.flush();
        em.clear();
        List<Member> result = memberRepository.findByUserName("member5");
        Member member5 = result.get(0);
        System.out.println("member5.getAge() = " + member5.getAge());


        //then
        Assertions.assertThat(resultCount).isEqualTo(3);

    }

영속성 컨텍스트를 초기화 후 엔티티를 조회하므로 DB에 조회 쿼리가 날라감. 

    select
        member0_.member_id as member_i1_0_,
        member0_.age as age2_0_,
        member0_.team_id as team_id4_0_,
        member0_.user_name as user_nam3_0_ 
    from
        member member0_ 
    where
        member0_.user_name=?
        
        
member5.getAge() = 41

 

4. GitHub : 210829 SpringDataJpa Bulk


 

GitHub - bsh6463/SpringDataJpa

Contribute to bsh6463/SpringDataJpa development by creating an account on GitHub.

github.com

 

'인프런 > [인프런] Spring Data JPA' 카테고리의 다른 글

JPA Hint & Lock  (0) 2021.08.29
@EntityGraph  (0) 2021.08.29
SpringDataJpa 페이징, 정렬  (0) 2021.08.29
JPA의 페이징과 정렬  (0) 2021.08.29
@Query, 반환 타입  (0) 2021.08.29
Comments