프록시란?
❓테이블을 조회해서 객체를 가져올 때 연관관계 객체는 안가져 오고 싶으면 어떻게 해야 할까?
em.find() : 데이터베이스를 통해서 실제 엔티티 객체 조회
em.getReference(): 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회
Member member = em.getReference(Member.class, 1L);
System.out.println("member = " + member.getClass()); // HibernateProxy 객체
getReference() 메서드를 사용하면 진짜 객체가 아닌 하이버네이트 내부 로직으로 프록시 엔티티 객체 반환
내부 구조는 틀은 같지만 내용이 비어있다.
프록시 객체를 반환한다.
특징
실제 클래스를 상속받아서 만들어짐
실제 클래스와 겉 모양이 같다.
사용하는 입장에서는 진짜 객체인지 구분 필요가 없다(이론적으로)
프록시 객체는 실제 객체의 참조(target)를 보관한다.
프록시 객체를 호출(getName())하면 프록시 객체는 실제 객체의 메소드 호출
프록시는 처음 사용할 때 한 번만 초기화
프록시 객체를 초기화 할 때 프록시 객체가 실제 엔티티로 바뀌는 것은 아님, 초기화되면 프록시 객체를 통해 실제 엔티티에 접근 가능
프록시 객체는 원본 엔티티를 상속받음, 따라서 타입 체크시 주의해야함( ==비교 실패, 대신 instance of 사용)
m1.getClass() == m2.getClass() //false
m1 instanceof Member // true
m2 instanceof Member // true
영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해도 실제 엔티티 반환
Member m1 = em.find(Member.class, member1.getId());
System.out.println("m1 = "+ m1.getClass());//Member
Member reference = em.getReference(Member.class, member1.getId());
System.out.println("reference = " reference.getClass()); //Member
m1 == reference //true
이미 Member를 1차캐시에도 올라와 있는데, 프록시를 반환할 필요가 없다.