TIL

[250411 TIL] 영속성 컨텍스트 심화

도원좀비 2025. 4. 11. 21:20

1️⃣ persist, merge, remove, detach — 영속성 컨텍스트

메서드 설명 주의할 점
persist(entity) 새 엔티티를 영속 상태로 등록 식별자가 없다면 자동 생성됨. 이미 있는 엔티티에 쓰면 예외 발생
merge(entity) 준영속 or 비영속 엔티티의 값을 복사해서 새 영속 엔티티 생성 원본 객체는 여전히 준영속 상태
remove(entity) 영속 상태인 엔티티를 삭제 예약 트랜잭션 커밋 시 delete 쿼리 실행됨
detach(entity) 엔티티를 영속성 컨텍스트에서 분리 → 준영속 상태로 전환 이후 변경해도 DB 반영 X
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

Member member = new Member("sukh"); // 비영속
em.persist(member); // 영속

em.detach(member); // 이제 준영속. 변경해도 DB 반영 안됨

em.getTransaction().commit();

2️⃣ 1차 캐시 & 동일성 보장 (== 비교 가능)

 

em.persist() 하면 DB에 insert 전이라도 1차 캐시에 올라감.

같은 트랜잭션 내에서 find() 하면 DB에서 가져오는 게 아니라 캐시에서 즉시 반환.

따라서 == 연산자로 비교해도 동일 객체로 간주됨.

Member member1 = em.find(Member.class, 1L);
Member member2 = em.find(Member.class, 1L);

System.out.println(member1 == member2); // true → 동일성 보장

 


3️⃣ 변경 감지 (Dirty Checking)

  • @Transactional 안에서 조회한 영속 상태 객체를 setter 등으로 변경하면,
  • 트랜잭션 커밋 시점에 flush()가 호출되어 변경 내용 감지 → update SQL 자동 생성

 

Member member = em.find(Member.class, 1L); // 영속
member.setName("newName"); // setter 사용

em.getTransaction().commit(); 
// 이 시점에 JPA가 이전 스냅샷과 비교해서 update 쿼리 날림

4️⃣ 요약

1. persist() → 비영속 → 영속

2. detach() → 영속 → 준영속

3. merge() → 복제본 생성 후 영속

4. remove() → 삭제 예약

5. 1차 캐시 덕분에 동일성 보장 (==도 OK)

6. 변경 감지는 커밋 직전 flush()에서 작동


5️⃣ 다음 공부 할 것

1. 지연 로딩과 즉시 로딩의 차이

2. Flush 타이밍 (트랜잭션 커밋, JPQL 실행 전 등)

3. 준영속 상태로 전환되는 시점과 활용법