
이전에 작성했던 영속성 컨텍스트, 더티 체킹과 이어지는 개념입니다.
트랜잭션 내에서 엔티티가 어떻게 관리되는지 이해하면 혼란이 줄어듭니다.
JPA에서는 엔티티가 트랜잭션과 영속성 컨텍스트 안에서 다음 4가지 상태를 가집니다.
| 상태 | 의미 | 상태 전이 메서드 | DB 반영 여부 |
|---|---|---|---|
| new / transient | 아직 DB와 연결되지 않은 새 객체 | persist() | ❌ |
| managed / persistent | 영속성 컨텍스트에 의해 관리되는 상태 | - | flush/commit 시 변경 감지 후 DB 반영 |
| detached / 준영속 | 영속성 컨텍스트에서 분리된 상태 | merge() | 기존 엔티티와 병합 시 반영 |
| removed | 삭제 예정 상태 | remove() | flush/commit 시 DELETE 실행 |
@Transactional
public void jpaLifecycle(EntityManager em) {
// new / transient
Member m = new Member("CHEETAH"); // 생성 직후
System.out.println("new? " + em.contains(m)); // false
// persist -> managed
em.persist(m);
System.out.println("managed? " + em.contains(m)); // true
em.flush(); // INSERT SQL 발생
// detach -> detached
em.detach(m);
System.out.println("detached? " + !em.contains(m)); // true
m.setName("WONT_SAVE"); // 아직 DB 반영 X
// merge -> managed 재진입
Member merged = em.merge(m);
merged.setName("OK"); // DB에 반영
// flush 시 UPDATE SQL 발생
// remove -> removed
em.remove(merged);
// flush 시 DELETE SQL 발생
}
Hibernate: insert into member (name, id) values (?, ?)
Hibernate: update member set name=? where id=?
Hibernate: delete from member where id=?
New → Managed: persist() 호출
Managed → Detached: detach() 또는 clear()
Detached → Managed: merge()
Managed → Removed: remove()
flush/commit 시점에 실제 SQL 실행
Member m = em.find(Member.class, id);
em.detach(m);
m.setName("NO UPDATE"); // UPDATE X
Member detached = new Member("OLD");
Member managed = em.merge(detached);
managed.setName("NEW"); // OK
detached.setName("FAIL"); // DB X
remove() 호출 후 flush 또는 commit 시 DELETE 발생
remove 전에도 setName 등 수정 가능 → flush 시 DELETE 우선
트랜잭션이 끝나면 managed 상태 엔티티는 자동으로 detach
따라서 트랜잭션 범위를 잘 정의해야 안전
엔티티를 DB에 처음 저장: persist()
영속성 컨텍스트에서 제외: detach(); / clear()
detached 엔티티 DB 반영: merge() → 반환값 사용
삭제: remove() -> flush/commit 시 DELETE
트랜잭션 범위 내에서 상태 변화 이해 필수
JPA 엔티티는 4가지 상태(New, Managed, Detached, Removed)로 구분되며
상태 전이를 이해하면 save(), merge(), remove() 동작의 차이를 명확히 알 수 있습니다.
영속성 컨텍스트 + 더티 체킹 + 엔티티 상태를 합쳐서 이해해야 실무에서 혼란을 예방합니다.
트랜잭션 범위, flush/commit, detach/merge 전략을 활용하면 안전하게 DB를 조작할 수 있어요.