JVM/JPA

즉시 로딩, 지연 로딩, 프록시

kyoulho 2023. 6. 23. 17:25

JPA 기본 페치 전략

연관된 엔티티가 하나면 즉시 로딩을, 컬렉션이면 지연 로딩을 사용한다.

모든 연관관계에 지연 로딩을 사용하고 개발 완료단계에 꼭 필요한 곳에만 즉시 로딩을 사용하는 것을 권장한다.

 

즉시 로딩

  • JPA는 선택적 관계면 외부 조인을 사용하고 필수 관계면 내부 조인을 사용한다. 외부 조인보다 내부 조인이 성능가 최적화에서 더 유리하므로 NULL을 허용하지 않는다면 JPA에게 확실히 알려주는 게 좋다.
  • 컬렉션 즉시 로딩은 항상 외부 조인을 사용한다.
@JoinColumn(nullable = false) 혹은 @ManyToOne(optional = false)

 

 

프록시

  • 프록시는 엔티티가 생성되어 있지 않으면 영속성 컨텍스트에 엔티티 생성을 요청하는데 이것을 초기화라 한다.
  • EntityManager.getReference() 메소드는 DB를 조회하지 않고 프록시 객체를 반환한다.
  • 프록시는 지연로딩 시 사용하기 위해 PK를 보관하고 있다.
    • 프로퍼티 접근으로 설정한 경우 getId()를 호출해도 초기화하지 않는다.
    • 필드 접근으로 설정한 경우 getId() 메소드가 id만 반환하는 메소드인지 아닌지 알 수 없기 때문에 초기화한다.
    • 연관관계를 설정할 때는 식별자 값만 사용하므로 프록시를 사용해도 초기화하지 않는다.
  • PersistenceUnitUtil.isLoaded(Object entity) 메소드를 사용하면 프록시 인스턴스의 초기화 여부를 확인할 수 있다.
    • 초기화되지 않은 프록시 인스턴스는 false를 반환한다.
    • 이미 초기화되었거나 프록시 인스턴스가 아니면 true를 반환한다.
  • 하이버네이트의 initialize() 메소드를 사용하면 강제로 초기화할 수 있다.
    • org.hibernate.Hbernate.intialize(order.getMember());

 

컬렉션 래퍼

 하이버네이트는 엔티티를 영속 상태로 만들 때 엔티티에 컬렉션이 있으면 컬렉션을 추적하고 관리할 목적으로 원본 컬렉션을 하이버네이트가 제공하는 내장 컬렉션(org.hibernate.collection.internal.PersistentBag)으로 변경하는데 이것을 컬렉션 래퍼라 한다.

 

 엔티티를 지연 로딩하면 프록시 객체를 사용해서 지연 로딩을 수행하지만 주문 내역 같은 컬렉션은 컬렉션 래퍼가 지연 로딩을 처리해 준다.

 

 컬렉션은 member.getOrders(). get(0)처럼 실제 데이터를 조회할 때 데이터베이스를 조회해서 초기화한다.

 

'JVM > JPA' 카테고리의 다른 글

임베디드 타입(복합 값 타입) @Embedded, @Embeddable  (0) 2023.06.24
영속성 전이, 고아 객체  (0) 2023.06.23
@SecondaryTable, @SecondaryTables  (1) 2023.06.19
@JoinTable  (0) 2023.06.19
@MapsId  (0) 2023.06.18