1. 소개
이 짧은 사용방법(예제)에서는 @ org.hibernate.annotations.Fetch 어노테이션 에서 사용할 수 있는 다양한 FetchMode 값을 살펴보겠습니다.
2. 예제 설정
예를 들어 ID와 주문 집합이라는 두 가지 속성만 있는 다음 Customer 엔터티를 사용합니다.
@Entity
public class Customer {
@Id
@GeneratedValue
private Long id;
@OneToMany(mappedBy = "customer")
@Fetch(value = FetchMode.SELECT)
private Set<Order> orders = new HashSet<>();
// getters and setters
}
또한 ID, 이름 및 고객 에 대한 참조로 구성된 주문 엔터티를 만듭니다 .
@Entity
public class Order {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "customer_id")
private Customer customer;
// getters and setters
}
다음 각 섹션에서는 데이터베이스에서 고객을 가져오고 모든 주문을 가져옵니다.
Customer customer = customerRepository.findById(id).get();
Set<Order> orders = customer.getOrders();
3. 가져오기 모드.선택
Customer 엔터티에서 @Fetch 어노테이션을 사용하여 주문 속성 에 어노테이션을 추가 했습니다 .
@OneToMany
@Fetch(FetchMode.SELECT)
private Set<Orders> orders;
@Fetch 를 사용 하여 Customer를 조회할 때 Hibernate가 속성을 검색하는 방법을 설명합니다 .
SELECT 를 사용 하면 속성을 느리게 로드해야 함을 나타냅니다.
이것은 첫 번째 줄에 대해 다음을 의미합니다.
Customer customer = customerRepository.findById(id).get();
주문 테이블과의 조인이 표시되지 않습니다.
Hibernate:
select ...from customer
where customer0_.id=?
그리고 다음 줄:
Set<Order> orders = customer.getOrders();
관련 주문에 대한 후속 쿼리가 표시됩니다.
Hibernate:
select ...from order
where order0_.customer_id=?
Hibernate FetchMode.SELECT 는 로드해야 하는 주문 마다 별도의 쿼리를 생성합니다 .
이 예제에서는 Customers를 로드하기 위한 하나의 쿼리와 주문 컬렉션을 로드하기 위한 5개의 추가 쿼리를 제공합니다.
이것은 n + 1 선택 문제로 알려져 있습니다. 하나의 쿼리를 실행하면 n개의 추가 쿼리 가 트리거됩니다 .
3.1. @ 배치 크기
FetchMode.SELECT 에는 @BatchSize 어노테이션을 사용하는 선택적 구성 어노테이션이 있습니다 .
@OneToMany
@Fetch(FetchMode.SELECT)
@BatchSize(size=10)
private Set<Orders> orders;
Hibernate 는 size 매개변수 에 의해 정의된 일괄 처리로 주문 컬렉션을 로드하려고 시도할 것입니다 .
이 예에서는 주문이 5개뿐이므로 하나의 쿼리로 충분합니다.
여전히 동일한 쿼리를 사용합니다.
Hibernate:
select ...from order
where order0_.customer_id=?
그러나 한 번만 실행됩니다. 이제 두 개의 쿼리만 있습니다. 하나는 고객 을 로드하고 다른 하나는 주문 컬렉션을 로드합니다.
4. 가져오기 모드 .결합
FetchMode.SELECT 가 관계를 느리게 로드 하는 동안 FetchMode.JOIN 은 조인을 통해 관계를 열심히 로드합니다.
@OneToMany
@Fetch(FetchMode.JOIN)
private Set<Orders> orders;
결과적으로 Customer 와 해당 주문 모두에 대해 하나의 쿼리만 생성됩니다 .
Hibernate:
select ...
from
customer customer0_
left outer join
order order1
on customer.id=order.customer_id
where
customer.id=?
5. 가져오기 모드.SUBSELECT
orders 속성은 컬렉션이므로 FetchMode.SUBSELECT를 사용할 수도 있습니다 .
@OneToMany
@Fetch(FetchMode.SUBSELECT)
private Set<Orders> orders;
컬렉션 에만 SUBSELECT 를 사용할 수 있습니다.
이 설정을 사용하여 고객 에 대한 하나의 쿼리로 돌아갑니다 .
Hibernate:
select ...
from customer customer0_
이번에는 하위 선택을 사용하여 Order 에 대한 하나의 쿼리 :
Hibernate:
select ...
from
order order0_
where
order0_.customer_id in (
select
customer0_.id
from
customer customer0_
)
6. FetchMode VS FetchType
일반적으로 FetchMode 는 Hibernate 가 데이터를 가져오는 방법을 정의합니다 (select, Join 또는 subselect를 통해). 반면에 FetchType 은 Hibernate가 데이터를 열심히 또는 느리게 로드할지 여부를 정의합니다.
이 둘 사이의 정확한 규칙은 다음과 같습니다.
- 코드가 FetchMode 를 설정하지 않으면 기본 값은 JOIN 이고 FetchType 은 정의된 대로 작동합니다.
- FetchMode.SELECT 또는 FetchMode.SUBSELECT 를 설정하면 FetchType 도 정의된 대로 작동합니다.
- FetchMode.JOIN 이 설정되면 FetchType 이 무시되고 쿼리가 항상 열망합니다.
자세한 내용은 Hibernate에서 Eager/Lazy Loading 을 참조하십시오 .
7. 결론
이 예제에서는 FetchMode 의 다양한 값과 FetchType 과의 관계에 대해 배웠습니다 .
항상 그렇듯이 모든 소스 코드는 GitHub에서 사용할 수 있습니다 .