Reference. 자바 ORM 표준 JPA 프로그래밍
책 목차 및 이전 글
더보기
- 영속 상태의 엔티티가 영속성 컨텍스트에서 분리된 상태를 의미
- 준영속 상태의 엔티티는 영속성 컨텍스트가 제공하는 기능 사용 못함
영속 상태 → 준영속 상태 만드는 방법 3가지
em.detach(entity)
: 특정 엔티티만 준영속 상태로 전환
em.clear()
: 영속성 컨텍스트를 완전히 초기화
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(); //트랜잭션 커밋
}
- 영속성 컨텍스트에서 관리하던(1차 캐시, 쓰기 지연 SQL 저장소) 정보를 제거
- 준영속 상태: 영속 상태였다가 영속성 컨텍스트가 관리하지 않는 상태 (분리된 상태)
3.6.2 영속성 컨텍스트 초기화: clear()
em.detach()
는 특정 엔티티 하나,em.clear()
는 모든 엔티티를 준영속 상태로 변경
//엔티티 조회, 영속 상태
Member member = em.find(Member.class, "memberA");
em.clear(); //영속성 컨텍스트 초기화
//준영속 상태
member.setUsername("changeName");
- 영속성 컨텍스트에 모든 것이 초기화
- 준영속 상태이므로 변경 감지는 동작하지 않음, 따라서 데이터베이스도 반영 안됌
3.6.3 영속성 컨텍스트 종료: close()
- 종료하면 영속성 컨텍스트 관리하던 영속 상태 엔티티가 모두 준영속 상태로 변경
- 영속 상태의 엔티티는 주로 영속성 컨텍스트가 종료되면서 준영속 상태로 변경
→ 개발자가 직접 준영속 상태로 만드는 일은 거의 없음
3.6.4 준영속 상태의 특징
- 거의 비영속 상태에 가깝다
- 영속성 컨텍스트가 관리하지 않으므로 1차 캐시, 쓰기 지연, 등 어떠한 기능도 동작 안함
- 식별자 값을 가지고 있다
- 비영속 상태는 식별자 값이 없을 수도 있지만 준영속 상태는 반드시 식별자 값을 가짐
- 지연 로딩을 할 수 없다
- 지연 로딩은 실제 객체 대신 프록시 객체를 로딩하여 영속성 컨텍스트를 통해 데이터를 불러오는 방법
- 영속성 컨텍스트가 관리하지 않으므로 지연 로딩시 문제 발생
*프록시 객체: (8.1 프록시 참고)
하이버네이트가 강제로 만든 가짜 클래스인 HibernateProxy 객체
- 실제 클래스를 상속 받아서 생성
- 하이버네이트가 내부적으로 상속받아서 생성
- 실제 클래스와 겉 모양이 동일
- 사용하는 입장에서는 진짜 객체인지 프록시 객체인지 구분하지 않고 사용
- 프록시 객체는 실제 객체의 참조(target)을 보관
- 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드를 호출
프록시 참조 출처: https://ict-nroo.tistory.com/131
3.6.5 병합: merge()
- 준영속 상태의 엔티티를 다시 영속 상태로 변경하는 기능
- 준영속 상태의 엔티티를 받아 그 정보로 새로운 영속 상태의 엔티티를 반환
그림 실행 순서
merge()
실행
- 파라미터로 넘어온 준영속 엔티티의 식별자 값으로 1차 캐시 엔티티 조회
- 만약 1차 캐시에 엔티티가 없으면 데이터베이스에서 조회 후 1차 캐시 저장
- 조회한 영속 엔티티에 member 엔티티의 값을 채움
→ mergetMember의 "회원1"이 member 엔티티의 "회원명변경"으로 변경 됌)
- mergetMember를 반환
- 병합이 끝나고 트랜잭션 커밋을 통해 변경감지 기능이 동작. 변경내용이 데이터베이스에 반영 됌
em.contains(entity)
: 영속성 컨텍스트가 파라미터에 엔티티를 관리하는지 확인하는 메소드
→ member는 false 반환, mergetMember는 true 반환
→merge()
후 준영속 엔티티를 참조하던 변수를 영속 엔티티 참조로 변경하는 것이 안전
//Member mergeMember = em2.merge(member); // 기존 코드
member = em2.merge(member);
비영속 병합
merge()
는 비영속 엔티티도 영속 상태로 변경이 가능
Member member = new Memeber();
Member newMember = em.merge(member); //비영속 병합
tx.commit();
- 파라미터로 넘어온 엔티티의 식별자 값으로 영속성 컨텍스트를 조회
→ 영속성 컨텍스트에 없으면 데이터베이스에서 조회
→ 데이터베이스에서도 없으면 새로운 엔티티를 생성해서 병합
- 병합은 준영속, 비영속을 신경쓰지 않음
- 조회할 수 있으면 불러서 병합, 조회가 안되면 새로 생성해서 병합 (save or update)
이미지 출처: https://ultrakain.gitbooks.io/jpa/content/chapter3/chapter3.4.html
'개발서적 > 자바 ORM 표준 JPA' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍] 4.4 - 4.5 데이터베이스 스키마 자동 생성, DDL 생성 기능 (0) | 2021.08.03 |
---|---|
[자바 ORM 표준 JPA 프로그래밍] 4.1 - 4.3 @Entity, @Table, 다양한 매핑 (0) | 2021.08.03 |
[자바 ORM 표준 JPA 프로그래밍] 3.5 플러시 (0) | 2021.07.28 |
[자바 ORM 표준 JPA 프로그래밍] 3.4 영속성 컨텍스트의 특징 (0) | 2021.07.28 |
[자바 ORM 표준 JPA 프로그래밍] 3.3 엔티티의 생명주기 (0) | 2021.07.28 |