T_era

변경 감지(Dirty Checking) 본문

Programing/Spring

변경 감지(Dirty Checking)

블스뜸 2025. 5. 15. 18:36

영속성 컨텍스트는 Entity의 초기 상태를 저장하고, 트랜잭션 커밋 시 현재 상태와 비교하여 변경 사항 유무를 확인하는 기능이다.

try {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("your_persistence_unit");
    EntityManager em = emf.createEntityManager();
    EntityTransaction transaction = em.getTransaction();
    transaction.begin();

    Tutor tutor = em.find(Tutor.class, 1L);
    tutor.setName("수정된 이름"); // 객체 값 변경 시 변경 감지

    System.out.println("트랜잭션 Commit 전");
    transaction.commit(); // Commit 시점에 UPDATE SQL 실행
    System.out.println("트랜잭션 Commit 후");
} catch (Exception e) {
    e.printStackTrace();
    transaction.rollback();
}

em.persist(tutor) 미사용 시에도 변경 감지 기능에 의해 UPDATE SQL이 실행된다. Entity 변경 시 em.persist() 사용은 지양해야 한다.

내부 동작

  1. 조회 시 스냅샷 저장: Entity 조회 시 영속성 컨텍스트의 1차 캐시에 저장됨과 동시에 해당 시점의 Entity 상태를 스냅샷으로 보관한다.
  2. transaction.commit() -> flush() 호출: 트랜잭션 커밋 시 JPA는 변경 내용 DB 반영을 위해 flush()를 호출한다.
  3. Entity와 스냅샷 비교: flush() 시 영속성 컨텍스트는 1차 캐시의 Entity와 스냅샷을 비교하여 변경된 Entity를 식별한다.
  4. UPDATE SQL 생성: 변경된 Entity에 대한 UPDATE SQL을 생성하여 쓰기 지연 저장소에 보관한다.
  5. flush() 완료: 쓰기 지연 저장소의 UPDATE SQL을 DB로 전송 및 실행한다.
  6. Commit: flush() 성공 시 트랜잭션을 DB에 최종 반영한다. flush() 실패 시 롤백될 수 있다.

내부 동작 요약: 조회 시 스냅샷 저장 -> flush() 시작 -> DB 반영 준비 -> flush() 완료 -> commit() 실행.

em.remove()를 통한 Entity 삭제 시에도 유사하게 동작하며, DELETE SQL은 트랜잭션 Commit 시점에 실행된다.

Flush

영속성 컨텍스트의 변경 내용을 DB에 반영하는 기능으로, 변경된 Entity 정보를 SQL로 변환하여 DB와 동기화한다. 트랜잭션 커밋 시 자동 호출되나, 필요 시 em.flush()로 수동 호출 가능하다.

Flush 사용 방법:

  • 자동 호출: 트랜잭션 Commit 시 자동 실행.
  • 수동 호출: em.flush()를 통해 명시적으로 호출.