QueryDSL - 수정, 삭제 벌크 연산

목차

수정, 삭제 벌크 연산

Bulk 연산은 영속성 Context 상태를 무시 하고 쿼리가 발생하기 때문에 영속성 Context 와 DB 상태가 다르게 된다.

UPDATE, DELETE 와 같은 대량의 데이터를 한번에 처리하는 Bulk 연산을 진행하게 되면 JPA 가 영속성 컨텍스트에 저장된 엔티티를 우회하고 직접 데이터베이스에 접근하기 때문에, 영속성 컨텍스트에 저장된 엔티티 상태와 DB 상태가 다르게 됩니다. 따라서 Bulk 연산시에는 영속성 컨텍스트와 DB 상태간의 데이터 동기화에 주의를 해야 합니다.

수정

@Test
public void bulkUpdate(){
long count = queryFactory
.update(member)
.set(member.username, "비회원")
.where(member.age.lt(28))
.execute();
}
/* update
Member member1
set
member1.username = ?1
where
member1.age < ?2 */ update
member
set
username=?
where
age<?
@Test
public void bulkUpdate(){
long count = queryFactory
.update(member)
.set(member.username, "비회원")
.where(member.age.lt(28))
.execute();

List<Member> result = queryFactory
.selectFrom(member)
.fetch();

for (Member member1 : result) {
System.out.println("member1 = " + member1);
}
}
  • Bulk 연산은 영속성 Context 상태를 무시하고 쿼리가 발생하기 때문에 영속성 Context 와 DB 상태가 다르게 된다.
member1 = Member(id=3, username=member1, age=10)
member1 = Member(id=4, username=member2, age=20)
member1 = Member(id=5, username=member3, age=30)
member1 = Member(id=6, username=member4, age=40)

영속성 컨텍스트와 DB 동기화 진행

Bulk 연산 후에는 영속성 컨텍스트와 DB 에 저장된 데이터간의 차이가 발생하기 때문에 데이터 불일치를 해결하기 위한 동기화 작업 이 필요합니다.

영속성 컨텍스트와 DB 와의 동기화를 진행하기 위해서는 일단 영속성 컨텍스트의 변경 사항을 Database 에 반영한 후 기존에 영속성 컨텍스트에 저장된 Entity 정보들을 비우고 Database 로부터 새롭게 Entity 정보를 가져오는 것으로 동기화를 진행할 수 있습니다.

우선, 영속성 컨텍스트의 변경 내용을 DB에 반영하기 위해 EntityManager 의 flush 메소드를 통해 쓰기 지연 SQL 저장소에 저장된 쿼리를 DB 로 보내 영속성 컨텍스트의 변경 내용을 DB에 반영합니다. 그 다음, 영속성 컨텍스트에서 DB 로부터 Entity 정보를 다시 가져와 저장할 수 있도록 clear 메소드를 통해 영속성 컨텍스트를 비워주도록 한다.

@Test
public void bulkUpdate(){
long count = queryFactory
.update(member)
.set(member.username, "비회원")
.where(member.age.lt(28))
.execute();

// 쓰기 지연 저장소에 저장된 SQL 을 DB 에 반영한다.
em.flush();
// 영속성 컨텍스트를 비운다.
em.clear();

List<Member> result = queryFactory
.selectFrom(member)
.fetch();

for (Member member1 : result) {
System.out.println("member1 = " + member1);
}
}

삭제

@Test
public void bulkDelete(){
long count = queryFactory
.delete(member)
.where(member.age.gt(18))
.execute();
}
Share