본문 바로가기
JPA

JPA - 준영속, 병합

by 왈레 2022. 4. 8.

1. 준영속

영속성 컨텍스트가 관리하는 영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)된 것을 준영속 상태라 한다.


준영속 상태의 엔티티는 영속성 컨텍스트가 제공하는 기능을 사용할 수 없다.

 

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

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

 

detach(Entity)

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

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

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

    transaction.commit();   //트랜잭션 커밋
}

detach가 호출되는 순간 1차 캐시부터 쓰기 지연 SQL저장소까지 해당 엔티티를 관리하기 위한 모든 정보가 제거된다.

 

 

clear()

em.clear();

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

 

close()

em.close();

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

 

준영속 상태의 특징

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

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

 

2. 식별자 값을 가지고 있다.

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

 

3. 지연 로딩을 할 수 없다.

지연 로딩시 문제가 발생

 

*지연로딩이란?

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

 

2. 병합(merge)

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

구체적인 과정은 다음과 같다.

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

변경 감지 기능을 사용하면 원하는 속성만 선택해서 변경할 수 있지만, 병합을 사용하면 모든 속성이 변경된다.

병합시 값이 없으면 null로 업데이트 할 위험도 있다. (병합은 모든 필드를 교체한다.)

병합은 편리하게 사용할 수 있다는 장점이 있지만, 모든 필드를 교체한다는 위험성 때문에 사용을 지양해야 한다.

 

※ 출처 - 인프런 김영한 JPA

'JPA' 카테고리의 다른 글

JPA - 필드와 컬럼 매핑  (0) 2022.04.09
JPA - 객체와 테이블 매핑 feat. 데이터베이스 스키마 자동생성  (0) 2022.04.08
JPA - 플러시  (0) 2022.04.08
JPA - 영속성 컨텍스트  (0) 2022.04.07
JPA를 배워야 하는 이유  (0) 2022.04.06

댓글