영속 -> 준영속
em.persist를 하면 영속 상태가 됩니다. 그런데 영속 상태가 되는 케이스가 하나 더 있습니다.
m.find로 DB에서 가져왔는데 영속성 컨텍스트에 없다고 칩시다. find("member2")를 했는데 1차 캐시에 없다면 DB에서 가져와서 1차 캐시에 올린다고 했습니다. 1차 캐시에 올라간 상태가 바로 영속 상태입니다. JPA가 관리하는 상태인 것입니다.
즉, JPA로 조회를 했을 때도 영속성 컨텍스트에 없다면 영속 상태가 됩니다.
준영속 상태는 영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)되는 것입니다. 한마디로 빼버리는 것입니다.
영속성 컨텍스트가 제공하는 기능을 사용 못함
먼저 코드로 확인합시다.
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory enf = Persistence.createEntityManagerFactory("hello");
EntityManager em = enf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Member member = em.find(Member.class, 150L);
member.setName("AAAAA");
em.detach(member);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
enf.close();
}
}
이전에 150번 조회해서 이름을 "ZZZZZ"로 바꿨습니다. 다시 "AAAAA"로 바꿔봅니다.
em.find로 데이터를 가져오면 member는 영속 상태입니다. 가져올 때 JPA가 영속성 컨텍스트에 없으니 150번을 올립니다. 그리고 값을 변경하니 변경 내역을 추적해서 커밋 시점에 update쿼리를 날린 것입니다.
그런데 더 이상 영속성 컨텍스트에서 관리하기 싫다면 em.detach(member);
를 해줍니다.
그럼 JPA에서 관리를 안하게 됩니다. 그래서 트랜잭션을 커밋할 때 아무일도 일어나지 않게 됩니다. 영속성 컨텍스트에서 다 빠져버린 것입니다.
실행해보겠습니다.
select 쿼리만 나가고 update 쿼리는 나가지 않습니다.
detach를 했기 때문입니다. 영속성 컨텍스트에서 더 이상 관리하지 말라고 끄집어냈습니다. 그래서 관련된 모든 것들이 영속성 컨텍스트에서 빠집니다.