Member 와 Team 이 연관관계로 매핑되어 있다 하자. 그럼 Member 만 조회해야 할 때도 있고, Team 만 조회 해야 할 때도 있고, Member 와 Team 을 모두 조회해야 할 때도 있따.
Member 와 Team 함께 출력
private static void printMemberAndTeam(Member member) {
String username = member.getUsername();
System.out.println("username = " + username);
Team team = member.getTeam();
System.out.println("team = " + team.getName();
Member 만 출력
private static void printMember(Member member) {
System.out.println("member = " + memebr.getUsername());
get.Reference() 사용하기
em.find() 를 사용하거나 Member 객체에 관한 출력만 필요한데도 Team 테이블까지 조인해 SELECT 쿼리를 전송한다.
// Member findMember = em.find(Member.class, member.getId());
Member findMember = em.getReference(Member.class, member.getId());
//System.out.println("findMember.id = " + findMember.getId());
//System.out.println("findMember.username = " + findMember.getUsername());
위의 코드에서 em.find() 코드를 주석 처리하고 대신 getReference() 를 사용해서 실행시키면 SELECT SQL 이 전송되지 않는다. 그럼 이번에 찾은 member 의 값을 꺼내는 출력문의 주석을 풀어보자.
그러면 이제 다시 또 Member 와 Team 을 JOIN 한 SELECT_SQL 이 실행된다.
em.getReference() 코드를 실행할 때는 쿼리가 발생하지 않는다. em.getReference() 로 찾아온 객체를 사용할 때에 SQL 쿼리가 발생하는데, findMember.getId() 의 경우엔 이미 em.getReference() 에서 member.getId() 값을 넣어주었으므로 DB까지 다녀오지 않아도 알 수 있는 값이라 이떄도 쿼리는 발생하지 않는다. 다만 find.getUsername() 은 DB 에서 조회를 해야지만 알 수 있는 값이기 때문에 이때 DB 에 SQL 문이 전달된다.
그럼 저 em.getReference() 로 가져온 findMember는 도대체 뭘까? 출력해보자.
System.out.println("findMember = " + findMember.getClass());
//출력로그
findMember = class hellojpa.Member$HibernateProxy$nizRdaZG
findMember 는 하이버네이트에서 만든 가짜 클래스이다.
Member memebr = em.getReference(Member.class, 1L);
member.getName();
초기화 이후 getName() 을 호출하면 DB 조회는 이루어지지 않고 target 에 값이 존재하니까 객체에 있는 값을 호출한다.
초기화 이후 getName() 을 호출하면 DB 조회는 이루어지지 않고 target 에 값이 존재하니까 객체에 있는 값을 호출한다.
프록시 객체는 처음 사용할 때 한 번만 초기화된다.
프록시 객체를 초기화 할 때, 프록시가 실제 엔티티로 교체되는게 아니라, 프록시 객체를 통해서 실제 엔티티에 접근이 가능한것이다.
프록시 객체는 원본 엔티티를 상속받는다. 따라서 타입 체크 시 주의해야 한다.
(== 비교 xxxxx, 대신 instance of를 사용해야 한다.)
위의 코드를 실행하면 에러가 터진다.
Member reference = em.getReference(Member.calss, memeber1.getId());
System.out.println("reference = " + reference.getClass()); //proxy
System.out.println("isLoaded = " + em.getPersistenceUnitUtil().isLoaded(reference); //fasle
//============//
Member reference = em.getReference(Member.class, memebr1.getId());
System.out.println("reference = " + reference.getClass()); //proxy
reference.getUsername();
System.out.println("isLoaded = " + emf.getPersistenceUnitUtil().isLoaded(reference); //true