[JPA] 프록시와 영속성 컨텍스트
프록시
Member를 조회할 때 Team도 함께 조회가 되는데 비효율적이지않나?
프록시 기초
- em.find() vs em.getReference()
- em.find() : 데이터베이스를 통해서 실제 엔티티 객체를 조회하게된다.
- em.getReference() : 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체를 조회한다.
프록시 특징
- 프록시 객체는 처음 사용할 때 한번만 초기화한다.
- 프록시 객체를 초기화 할 때, 프록시 객체가 실제 엔티티로 바뀌는것이 아니라 초기화되면 실제 엔티티에 접근이 가능한것임
- 프록시 객체는 원본 엔티티를 상속받음, 따라서 타입 체크시 == 비교 대신, instance of 사용
- 영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference() 호출해도 실제 엔티티 호출 ( 이 반대도 성립 )
- 영속성 컨텍스트의 도움을 받을수 없는 준영속 상태일때, 프록시를 초기화 할 때 문제발생
- ( 하이버네이트는 org.hibernate.LazyInitializationException 예외를 터트림 )
- 프록시 객체는 실제 객체의 참조(target)를 보관한다.
- 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드를 호출한다.
프록시 객체의 초기화
Member member = em.getReference(Member.class, "id1");
member.getName();
위 코드 실행시..
- 위 사진에서 알 수 있는것은 영속성 컨텍스트를 닫거나 준영속성 컨텍스트 상태라면 프록시 초기화에 문제가 발생한다.
프록시 확인
- 프록시 인스턴스의 초기화 여부 확인
- PersistenceUnitUil.isLoaded(Obejct entity)
- 프록시 클래스 확인 방법
- entity.getClass().getName() 출력
- 프록시 강제 초기화
- org.hibernate.Hibernate.initialize(entity)
- 강제 호출 : member.getName() 식으로 진행, JPA 표준은 강제 초기화없음
😄 참고 : 인프런 김영한님의 JPA 기본 강의 및 교재
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
개인메모