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에서 사용할 수 있습니다 .

Persistence footer banner