Proxy와 지연로딩

타마타마·2022년 7월 21일
0

JPA

목록 보기
4/10

JPA는 Member와 Team이 매핑이 되어 있는 경우 Team의 데이터를 모두 가져오게 된다.
그럼 Member를 호출할 때 Team이 같이 호출되는 것이 아닌
직접적으로 team의 데이터를 호출할 때 DB를 갔다 오면 안될까?

가능하다.

Proxy

  • 프록시 객체는 처음 사용할 때 한 번만 초기화
  • 초기화되면 프록시 객체를 통해서 실제 엔티티에 접근 가능
  • 영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해도 실제 엔티티 반환
  • 준영속 상태일 때, 프록시를 초기화하면 문제 발생

초기화되면 프록시 객체를 통해서 실제 엔티티에 접근 가능

Member refMember2 =em.getReference(Member.class, member.getId());
System.out.println(refMember2.getClass());
//class org.example.Member$HibernateProxy$pA2dQZkM

System.out.println(refMember2.getUsername());//proxy 초기화

System.out.println(refMember2.getClass());
//class org.example.Member$HibernateProxy$pA2dQZkM

/*
*  proxy 는 실제 엔티티로 변경되는 것이 아닌, 엔티티에 접근하는 것
*  따라서 초기화 했다고 값이 변경되지 않음.
*

영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해
도 실제 엔티티 반환 ( 반대인 경우 Proxy반환 == 마찬가지 )

//getReference 한 후 find

//find 한 후 getReference
Member m1 = em.find(Member.class, member.getId());
System.out.println("m1 >>" +  m1.getClass());//Member >> find로 가져옴

Member reference = em.getReference(Member.class, member.getId());//getReference() 사용 >> proxy 사용
reference.getUsername();//proxy 초기화 >> proxy target에 영속성 컨테스트 초기화 하여 DB 접근
System.out.println("reference >> " + reference.getClass());//Member

System.out.println("m1 == reference" + (m1.getClass() == reference.getClass())); // true

//getReference 한 후 find

//getReference 한 후 find
Member refMember = em.getReference(Member.class, member.getId());//proxy 사용
refMember.getUsername();//proxy 초기화 >> proxy target에 영속성 컨테스트 초기화 하여 DB 접근

System.out.println("refMember >> " + refMember.getClass());//proxy
//class org.example.Member$HibernateProxy$NM3yUT0g

Member findMember =em.find(Member.class, member.getId());
System.out.println("findMember >>" +  findMember.getClass());//proxy
//class org.example.Member$HibernateProxy$NM3yUT0g

System.out.println("findMember == refMember" + (findMember.getClass() == refMember.getClass()));
//true

Proxy 메서드

  1. 프록시 강제 초기화
    org.hibernate.Hibernate.initialize(entity);
  2. 프록시 인스턴스의 초기화 여부 확인
    PersistenceUnitUtil.isLoaded(Object entity)

지연로딩 해야하는 경우

모든 곳에 (fetch = FetchType.LAZY) 사용할 것

  • @ManyToOne,@OneToOne은 Default 값이 EAGGER 임 . >> LAZY로 변경해서 사용할 것

0개의 댓글