원본 코드를 바탕으로 조금씩 순서를 바꿔가며 실행했을 때의 결과를 알아보자.
// 객체를 생성한 상태 (비영속)
Member member = new Member();
member.setId("100L");
member.setUsername("회원1");
// 트랜잭션 시작
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
// 객체를 저장한 상태 (영속)
em.persist(member);
// 트랜잭션 커밋
tx.commit();
// 회원 엔티티를 영속성 컨텍스트에서 분리 (준영속)
em.detach(member);
// 객체를 삭제한 상태 (삭제)
em.remove(member);
// 객체를 생성한 상태 (비영속)
Member member = new Member();
member.setId("100L");
member.setUsername("회원1");
// 트랜잭션 시작
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
// 객체를 저장한 상태 (영속)
em.persist(member);
member 엔티티가 영속성 컨텍스트에는 올라가지만 트랜잭션 커밋을 하지 않아 데이터베이스에는 존재하지 않는다.
->트랜잭션 커밋을 해주어야 insert 쿼리가 날아가 데이터베이스에 반영된다.
// 객체를 생성한 상태 (비영속)
Member member = new Member();
member.setId("100L");
member.setUsername("회원1");
// 트랜잭션 시작
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
// 객체를 저장한 상태 (영속)
em.persist(member);
// 트랜잭션 커밋
tx.commit();
member 엔티티가 영속성 컨텍스트와 데이터베이스 모두에 올라가 있다.
// 객체를 생성한 상태 (비영속)
Member member = new Member();
member.setId("100L");
member.setUsername("회원1");
// 트랜잭션 시작
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
// 객체를 저장한 상태 (영속)
em.persist(member);
// 회원 엔티티를 영속성 컨텍스트에서 분리 (준영속)
em.detach(member);
// 트랜잭션 커밋
tx.commit();
영속성 컨텍스트에 member 엔티티를 올린 후 바로
detach()
메소드로 준영속 상태로 만들었다. 이 상태에서 트랜잭션 커밋을 하게되면 JPA가IllegalStateException
예외를 던지며 영속성 컨텍스트에 해당 엔티티가 존재하지 않는다고 한다.
->detach() 는 영속성 컨텍스트에 저장된 엔티티를 분리하는 메소드이기 때문에 트랜잭션 커밋을 할 수가 없다.
// 객체를 생성한 상태 (비영속)
Member member = new Member();
member.setId("100L");
member.setUsername("회원1");
// 트랜잭션 시작
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
// 객체를 저장한 상태 (영속)
em.persist(member);
// 회원 엔티티를 영속성 컨텍스트에서 분리 (준영속)
em.detach(member);
// 트랜잭션 커밋
tx.commit();
회원 엔티티를 영속화한 후 바로 준영속화 하였다. 이 상태에서 트랜잭션 커밋을 하면
IllegalStateException
예외가 발생한다. 이는 회원 엔티티가 준영속 상태이기 때문에 영속성 컨텍스트에서 관리되지 않아 변경 사항을 적용할 수 없기 때문이다.
// 객체를 생성한 상태 (비영속)
Member member = new Member();
member.setId("100L");
member.setUsername("회원1");
// 트랜잭션 시작
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
// 객체를 저장한 상태 (영속)
em.persist(member);
// 회원 엔티티를 영속성 컨텍스트에서 분리 (준영속)
em.detach(member);
// 트랜잭션 커밋
tx.commit();
// 데이터베이스에서 회원 엔티티 찾기
Member foundMember = em.find(Member.class, 100L);
// 찾은 회원 엔티티를 다시 영속화하기
em.merge(foundMember);
// 트랜잭션 커밋
tx.commit();
데이터베이스에 저장되었지만 준영속 상태인 엔티티에 다시 접근하려면 영속화해야 한다. 영속화 하기 위해서는 데이터베이스에서 해당 회원 엔티티를 찾아야하므로 pk 값으로 엔티티를 조회하는
find()
메소드를 사용하면 된다.
찾은 후 영속화 메소드인merge()
로 영속화해주면 다시 회원 엔티티에 접근할 수 있다.
-> persist() 도 영속화 메소드이지만 보통 새로 생성한 엔티티를 영속화할 때 주로 사용한다. 이미 영속성 컨텍스트에 존재하는 엔티티를 다시 영속화할 때는 merge() 를 사용한다.