728x90
em.find() vs em.getReference()
em.find는 DB를 통해 실제 엔티티 객체를 조회
em.getRefrence()는 DB조회를 미루는 가짜(프록시)엔티티 객체 조회
프록시?
- 실제 클래스를 상속받아 만들어져서 실제 클래스와 겉 모양이 같다.
- 사용하는 입장에서는 진짜 객체인지 프록시 객체인지 구분하지 않고 사용해도 됨(이론상)
- 프록시 객체는 실제 객체의 참조 target을 보관하고 있음.
- 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드를 호출함.
프록시 객체를 통해 메소드를 호출하면 다음과 같은 순서로 프록시 객체 초기화가 이루어진다.
1. 프록시 객체의 메소드를 호출
2.영속성 컨텍스트에 초기화 요청
3. 영속성 컨텍스트는 DB를 조회하여 실제 객체를 찾음.
4. 조회한 실제 객체를 프록시 객체의 target에 등록,
5. target.메소드를 호출
프록시의 특징
- 프록시 객체는 처음 사용할 때 한 번만 초기화된다.
- 프록시 객체를 초기화 할때, 프록시 객체가 실제 엔티티로 바뀌는 것이 아니다. 초기화되면서 프록시 객체를 통해 엔티티 객체에 접근 가능하게 된다.
- 프록시 객체는 원본 엔티티를 상속받으므로 타입 체크시 ==비교가 아니라, instance of를 사용해야 한다.
Member m1 = em.find(Member.class, 1L);
Member m2 = em.getReference(Member.class,2L);
m1.class == m2.class;//false
m1 instanceof Member;//true
m2 instanceof Member;//true
- 영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해도 실제 엔티티가 반환된다. (JPA는 동일한 객체 둘 사이의 ==비교가 true가 되도록 해주기때문이다. 반대로, em.find()해도 프록시객체가 나올 수 있다.)
- 프록시 객체의 초기화는 영속성 컨텍스트를 통해 진행되기 때문에, 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태일 때 프록시를 초기화하면 문제가 발생한다.(no session)
프록시 확인
프록시 인스턴스의 초기화 여부 확인
PersistenceUnitUtil.isLoaded(Object entity)
//emf.getPersistenceUnitUtil.isLoaded(refMember); 처럼 사용
프록시 클래스 확인 방법
entity.getClass().getName();
프록시 강제 초기화
org.hibernate.Hibernate.initialize(entity);
//Hibernate.initialize(refMember);
(하이버네이트 제공으로 JPA는 강제 초기화 지원 안함)
728x90
'웹개발 > JPA' 카테고리의 다른 글
영속성 전이 CASCADE (0) | 2023.07.19 |
---|---|
즉시 로딩과 지연 로딩 (0) | 2023.07.16 |
@MappedSuperclass (0) | 2023.07.07 |
상속관계 매핑 (0) | 2023.07.07 |
다양한 연관관계 (0) | 2023.07.03 |
댓글