JPA

8.3.1 프록시와 컬렉션 래퍼

fmoths 2021. 1. 16. 13:32

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

 

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

 

member.getOders();를 호출해도 컬렉션은 초기화 되지 않는다. 컬렉션은 members.getOrders().get(0) 처럼 컬렉션에서 실제 데이터를 조회할 때 데이터 베이스를 조회해서 초기화한다.

 

8.3.2 JPA 기본 페치 전략

- @ManyToOne, @OneToOne : 즉시로딩(FetchType.EAGER)

- @OneToMany, @ManyToMany : 지연로딩(FetchType.LAZY)

 

JPA의 기본페치 전략은 연관된 엔티티가 하나면 즉시로딩을, 컬렉션이면 지연로딩을 사용한다. 컬렉션을 로딩하는 것은 비용이 많이 들고 잘못하면 너무 많은 데이터를 로딩할 수 있기 때문이다.

 

때문에 모든 연관관계에 지연로딩을 사용하는 것을 추천한다.

 

8.3.3 컬렉션에 FetchType.EAGER 사용 시 주의점

- 컬렉션을 하나이상 즉시 로딩하는 것은 권장하지 않는다.

- 컬렉션과 조인한다는 것은 일대다 조인이다. 일대다 조인은 결과 데이터가 다쪽에 있는 수만큼 증가하게 된다.

- 따라서 2개이상의 컬렉션을 즉시 로딩으로 설정하는 것은 권장하지 않는다.

 

- 컬렉션 즉시로딩은 항상 외부 조인을 사용한다.

- 다대일 관계인 회원 테이블과 팀 테이블을 조인할 때 회원 테이블의 외래 키에 NOT NULL 제약조건을 걸어두면 모든 회원은 팀에 소속되므로 항상 내부 조인을 사용해도 된다. 반대로 팀 테이블에서 회원 테이블로 일대다 조인을 할때 회원이 한명도 없는 팀을 내부 조인하면 팀까지 조회되지 않는 문제가 발생한다. 따라서 JPA는 일대다 관계를 즉시 로딩할때 항상 외부 조인을 사용한다.

 

- @ManyToOne, @OneToOne

- (optional = false): 내부조인

- (optional = true): 외부조인

 

- @OneToMany, @ManyToMany

- (optional = false): 외부조인

- (optional = true): 외부조인