✅ em.getReference()
다음 두가지 경우가 있다고 해보자
public void printUserAndTeam(String memberId) {
Member member = em.find(Member.class, memberId);
Team team = member.getTeam();
System.out.println("회원 이름: " + member.getUsername());
System.out.println("소속팀: " + team.getName());
}
public void printUser(String memberId) {
Member member = em.find(Member.class, memberId);
Team team = member.getTeam();
System.out.println("회원 이름: " + member.getUsername());
}
회원과 팀을 항상 함께 출력한다면 문제가 되지 않지만
회원만 출력하는 경우에는 팀까지 불러올 필요가 없으므로 낭비가 생긴다.
이를 해결하기 위해 jpa에서 프록시와 지연로딩을 지원한다.
데이터베이스를 통해서 실제 엔티티 객체 조회
데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회
즉, em.getReference()가 선언되는 시점에는 db에 쿼리가 안찍히고
실제로 사용되는 시점에 db에 쿼리를 찍어 조회함
Member m1 = em.find(Member.class, member1.getId());
Member m2 = em.find(Member.class, member2.getId());
Member m3 = em.getReference(Member.class, member3.getId());
System.out.println("m1 == m2 : " + (m1.getClass() == m2.getClass())); // true
System.out.println("m1 == m3 : " + (m1.getClass() == m3.getClass())); // false
System.out.println("m3 : " + (m3 instanceof Member)); // true
Member member = em.getReference(Member.class, “id1”);
member.getName();
영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태일 때, 프록시를 초기화하면 문제가 발생한다.
Member member = em.getReference(Member.class, “id1”);
em.detach(member); // or em.close();
member.getName();
em.detach 나 em.close에 의해 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태가 되기 때문에 이후 프록시를 초기화 하면 문제(에러)가 발생한다.
(하이버네이트가 org.hibernate.LazyInitializationException 예외를 터트림)
emf.getPersistenceUnitUtil.isLoaded(Object entity)
entity.getClass()
org.hibernate.Hibernate.initialize(entity);