3.6 준영속

준영속 상태를 만드는 방법 3가지

번호 메소드 설명
1 em.detach(entity) 특정 엔티티만 준영속 상태로 전환
2 em.clear() 영속성 컨텍스트를 완전히 초기화
3 em.close() 영속성 컨텍스트를 종료

3.6.1 엔티티를 준영속 상태로 전환 : detach()

public void testDetached() {
    ...
    // 회원 엔티티 생성, 비영속 상태
    Member member = new Member();
    member.setId("memberA");
    member.setUsername("회원A");

    // 회원 엔티티 영속 상태
    em.persist(member);

    // 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
    em.detach(member);

    transaction.commit();   //트랜잭션 커밋
}
  • em.detach(member)
  • 해당 엔티티를 관리하지 말라는 것
  • 메소드를 호출하는 순간 1차 캐시부터 쓰기 지연 SQL저장소까지 해당 엔티티를 관리하기 위한 모든 정보가 제거

  • 영속 상태였다가 더는 형속성 컨텍스트가 관리하지 않는 상태를 준영속 상태.
  • 준영속 상태는 영속성 컨텍스트로부터 "분리된 상태".

3.6.1 영속성 컨텍스트를 초기화 : clear()

영속성 컨텍스트를 초기화해서 해당 영속성 컨텍스트의 모든 엔티티를 "준영속 상태"로 만든다.

//엔티티 조회, 영속 상태
Member member = em.find(Member.class, "memberA");

em.clear();     //영속성 컨텍스트 초기화

//준영속 상태
member.setUsername("changeName");

영속성 컨텍스트 초기화 전

영속성 컨텍스트 초기화 후

  • memberA, memberB -> 준영속 상태

3.6.1 영속성 컨텍스트 종료 : close()

영속성 컨텍스트를 종료하면 해당 영속성 컨텍스트가 관리하던 영속 상태의 엔티티가 모두 준영속 상태가 된다.

public void closeEntityManager() {

    EntityManagerFactory emf = 
        Persistence.createEntityManagerFactory("jpabook");

    EntityManager em = emf.createEntityManager();
    EntityTransaction transaction = em.getTransaction();

    transaction.begin();    // [트랜잭션] - 시작

    Member memberA = em.find(Member.class, "memberA");
    Member memberB = em.find(Member.class, "memberB");

    transaction.commit();   // [트랜잭션] = 커밋

    em.close();     // 영속성 컨텍스트 닫기(종료)
}

영속성 컨텍스트 제거 전

영속성 컨텍스트 제거 후

더는 memberA, memberB를 관리하지 않는다.

개발자가 직접 준영속 상태를 만드는 일은 드물다.

3.6.4 준영속 상태의 특징

거의 비영속 상태에 가깝다.

1차 캐시, 쓰기 지연, 변경 감지, 지연 로딩을 포함한 영속성 컨텍스트가 제공하는 어떤 기능도 동작하지 않는다.

식별자 값을 가지고 있다.

준영속 상태는 이미 한 번 영속 상태였으므로 반드시 식별자 값을 가지고 있다.

지연 로딩을 할 수 없다.

지연 로딩시 문제가 발생.

지연 로딩 - 실제 객체 대신 프록시 객체를 로딩해두고 해당 객체를 실제 사용할 때 영속성 컨텍스트를 통해 데이터를 불러오는 방법

3.6.5 병합 : merge()

  • 준영속 상태의 엔티티를 다시 영속 상태로 변경하려면 병합(merge)를 사용하면 된다.
  • merge() 메소드는 준영속 상태의 엔티티를 받아서 그 정보로 새로운 영속 상태의 엔티티를 반환.
// merge() 메소드 정의
public <T> T merge(T entity);
// 사용 예
Member mergeMember = em.merge(member);

준영속 병합

  1. merge()를 실행한다.
  2. 파라미터로 넘어온 준영속 엔티티의 식별자 값으로 1차 캐시에서 엔티티를 조회
  3. 만약 1차 캐시에 엔티티가 없으면 데이터베이스에서 엔티티를 조회하고 1차 캐시에 저장
  4. 조회한 영속 엔티티(mergeMember)에 member 엔티티의 값을 채워 넣는다.(member 엔티티의 모든 값을 mergeMember에 밀어넣는다. 이때 mergeMember의 "회원1"이라는 이름이 "회원명 변경"으로 바뀐다.
  5. mergeMember를 반환.

비영속 병합

Member member = new Member();
Member newMember = em.merge(member);    //비영속 병합
tx.commit();
  1. 파라미터로 넘어온 엔티티의 식별자 값으로 영속성 컨텍스트를 조회.
  2. 엔티티가 없으면 데이터베이스에서 조회.
  3. 데이터베이스에서도 발견하지 못하면 새로운 엔티티를 생성해서 병합.

병합은 준영속, 비영속을 신경쓰지 않는다.
식별자 값으로 엔티티를 조회할 수 있으면 불러서 병합.
조회할 수 없으면 새로 생성해서 병합.

results matching ""

    No results matching ""