[JPA] Dirty Checking과 Flush

JPA Dirty Checking 과 Flush

  • JPA에서는 더티 체킹을 통해 변경된 엔티티의 데이터만 flush한다
  • 엔티티에 대한 메타 데이터는 PersistenceContext 내에서 보관하고 수정사항이 있는지 여부를 체크해 업데이트를 수행한다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@BeforeEach
public void init() {
coffeeRepository.save(Coffee.builder().name("test-coffee").cost(1000).build());
}

@Test
public void dirtyChecking_test() {
/* given */
Coffee coffee = entityManager.find(Coffee.class, 1);
String name = coffee.getName();
int cost = coffee.getCost();

/* when */
coffee.modify("modify", -99999);

entityManager.flush();


Coffee coffee2 = entityManager.find(Coffee.class, 1);

/* then */
Assertions.assertNotEquals(name, coffee2.getName());
Assertions.assertNotEquals(cost, coffee2.getCost());
}

entityManager.find()

  • entityManager.find(Coffee.class, 1);를 하는 순간 엔티티를 조회해 와 EntityEntry를 생성한다.
  • 이 엔트리는 loadedState로 영속성 컨텍스트에 들어올 당시의 프로퍼티들을 가지고 있게 된다.
  • 그리고 이 엔트리와 연관된 엔티티를 페어로 묶어 영속성 컨텍스트에 저장한다.

entityManager.flush()

  • 이제 flush()를 하면 FlushEventListener에서 영속성 컨텍스트에 접근해 관리중이던 엔트리 페어를 가져온다.
  • 엔트리 페어의 Status를 확인하고 적합한 엔트리들을 FlushEntityEventListner로 넘긴다.
  • FlushEntityEventListner는 더티체킹이 필요한 엔티티인지 와 엔티티와 loadedState를 통해 더티 프로퍼티가 존재하는지 등을 확인하고 필요한 엔티티라면 업데이트 액션을 추가한다.
  • 업데이트 액션에서 Write Lock을 잡고 DB에 flush를 하면서 영속성 컨텍스트에 저장된 엔티티의 loadedState값을 변경된 updateState로 바꾸게 된다.
Author: Song Hayoung
Link: https://songhayoung.github.io/2022/01/17/JPA/jpa-dirty-checking/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.