ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Querydsl - 수정, 삭제 벌크 연산
    Spring/Querydsl 2022. 3. 25. 15:25
    728x90
    반응형

     

    수정, 삭제 벌크 연산

     여러개 수정, 삭제를 하면 데이터 수만큼 쿼리가 나가지만 벌크 연산을 사용하면 쿼리가 1번만 나간다. 따라서 여러개 수정, 삭제를 할 때는 벌크 연산을 사용하면 성능이 최적화된다.

     

     

    @Test
    @DisplayName("벌크 연산")
    public void bulkUpdate() {
        long count = queryFactory
                .update(member)
                .set(member.username, "비회원")
                .where(member.age.lt(28))
                .execute();
    
        assertThat(count).isEqualTo(2);
    }
    • count : 업데이트가 수행된 수
    • execute() : 벌크 연산 수행
        /* update
            Member member1 
        set
            member1.username = ?1 
        where
            member1.age < ?2 */ update
                member 
            set
                username=? 
            where
                age<?

     

     참고로 해당 쿼리가 실행된 이후에는 해당 쿼리로 DB에는 값이 변경되지만 영속성 컨텍스트에는 값이 변경되지 않는다. 따라서 벌크 연산이 수행된 이후 같은 트랙잭션에서 변경된 값을 DB에서 가져오면 이미 영속성 컨텍스트에 해당 데이터가 이미 있기 때문에 영속성 컨텍스트 안에 변경되지 않은 데이터 값을 가져오는 문제가 발생한다. 

     

     따라서 벌크 연산 이후 같은 트랜잭션에서 다시 조회할 경우에는 em.flush()와 em.clear()를 해줘야 한다.

     


     

    em.flush()와 em.clear()를 해줘야 하는 이유

     

    벌크 연산 수행 전

    memberDto = MemberDto(username=member1, age=10)
    memberDto = MemberDto(username=member2, age=20)

    memberDto = MemberDto(username=member3, age=30)

    memberDto = MemberDto(username=member4, age=40)

     

     

    벌크 연산 수행 후(영속성 컨텍스트)

    memberDto = MemberDto(username=member1, age=10)
    memberDto = MemberDto(username=member2, age=20)

    memberDto = MemberDto(username=member3, age=30)

    memberDto = MemberDto(username=member4, age=40)

     

    벌크 연산 수행 후(DB)

    memberDto = MemberDto(username=비회원, age=10)
    memberDto = MemberDto(username=비회원, age=20)

    memberDto = MemberDto(username=member3, age=30)

    memberDto = MemberDto(username=member4, age=40)

     

    Member PK 1,2 조회

    memberDto = MemberDto(username=member1, age=10) 
    memberDto = MemberDto(username=member2, age=20)

    → DB에 가져오기 이전에 이미 영속성 컨텍스트에 해당 member가 있기 때문에 업데이트 된 

       member 값이 아닌 영속성 컨텍스트에 있는 업데이트가 실행 안된 값을 가져오게 된다.

     

    728x90
    반응형

    댓글

Designed by Tistory.