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)처럼 실제 데이터를 조회할 때 데이터베이스를 조회해서 초기화한다.
728x90
'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 |