프록시와 연관관계 관리

프록시

@Enitity
public class Member {
  private String username;

  @ManyToOne
  private Team team;

  ...
}
  • 지연로딩(lazy loading)이란 엔티티가 사용될때 까지 데이터베이스에서 조회를 지연하는 것
  • 사용전까지 가짜 객체가 대신하는데 이를 프록시 객체라고 함

프록시 기초

  • find()는 영속성 컨텍스트에 엔티티가 없으면 사용여부와 관계없이 데이터베이스를 조회
  • getReference()는 데이터베이스를 조회하지 않고 엔티티 객체도 생성하지 않음, 데이터베이스 접근을 위임한 프록시 객체를 반환
// 즉시 조회
Member member = em.find(Member.class, "member1");

// 지연 조회
Member member = em.getReference(Member.class, "member1");
  • 프록시 객체는 처음 사용할 때 한 번만 초기화
    • 프록시 객체는 실제 객체에 대한 참조를 보관
    • 프록시 객체를 통해 실제 엔티티에 접근 가능
  • 프록시는 실제 클래스를 상속받아서 만들어짐
    • 사용하는 입장에서는 진짜 객체인지 프록시 객체인지 구분하지 않음
    • 타입 체크시 주의
  • 접근할 엔티티가 영속성 컨텍스트에 존재하면 데이터베이스 조회하지 않고 실제 엔티티 반환
  • 초기화는 영속성 컨텍스트의 도움을 받아야 가능
    • 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태의 프록시를 초기화하면 org.hibernate.LazyInitializationException 예외 발생
      • JPA 표준 명세는 지연 로딩(프록시)에 대한 내용을 JPA 구현체에 맡김
      • 따라서 준영속 상태의 엔티티를 초기화할때 어떤일이 발생할지에 대한 표준이 없음
      • 위 예외는 하이버네이트 사용시 발생
// 프록시 반환
Member member = em.getReference(Member.class, "member1");
transaction.commit();
em.close(); // 영속성 컨텍스트 종료

member.getName(); // 준영속 상태에서 초기화 시도, 예외 발생

프록시와 식별자

프록시와 확인

즉시 로딩과 지연 로딩

즉시 로딩

지연 로딩

지연 로딩 활용

영속성 전이: CASCADE

고아 객체

영속성 전이 + 고아 객체, 생명주기

정리