본문 바로가기
  • 실행력이 모든걸 결정한다
Spring 사전 준비/JPA Hibernate

[JPA] 엔티티 그래프

by 김코더 김주역 2022. 8. 25.
반응형

1. 엔티티 그래프 소개

- JPA 2.1에 추가된 기능으로, 객체 지향 쿼리를 사용하지 않고도 엔티티를 조회하는 시점에 함께 조회할 연관된 엔티티를 선택할 수 있다.

- 엔티티 그래프는 항상 조회하는 엔티티의 루트에서 시작해야 한다.

- 글로벌 fetch 전략보다 우선 순위가 높다.

- 영속성 컨텍스트에 이미 로딩되어 있는 엔티티에 대해서는 엔티티 그래프가 적용되지 않는다. 아직 초기화되지 않은 프록시에는 엔티티 그래프가 적용된다.

- 엔티티 그래프는 정적으로 정의하는 Named 엔티티 그래프와 동적으로 정의하는 엔티티 그래프가 있다.

 

 

 

2. Named 엔티티 그래프

1) Named 엔티티 그래프 정의

- @NamedEntityGraph 어노테이션으로 정의한다. name 속성에는 엔티티 그래프의 이름을 지정하고, attributeNodes 속성에는 함께 조회할 필드를 @NamedAttributeNode 어노테이션을 사용하여 선택하면 된다.

@NamedEntityGraph(name="Order.withMember", attributeNodes={
    @NamedAttributeNode("member")
})
@Entity
public class Order {

    ...
    @ManytoOne(fetch=FetchType.LAZY, optional=false)
    @JoinColumn(name="MEMBER_ID")
    private Member member;
}

※ 둘 이상의 @NamedEntityGraph를 정의하려면 @NamedEntityGraphs를 사용한다.

 

 

2) EntityManager.find()에서 엔티티 그래프 사용

- EntityManager.getEntityGraph() 메소드의 파라미터로 엔티티 그래프의 이름을 넣으면 EntityGraph 객체를 반환한다. 이 EntityGraph 객체를 Map에 넣어 힌트를 만들 수 있다.

EntityGraph graph = em.getEntityGraph("Order.withMember");

Map hints = new HashMap();
hints.put("javax.persistence.fetchgraph", graph);

Order order = em.find(Order.class, orderId, hints);

※ javax.persistence.fetchgraph 속성은 엔티티 그래프에 선택한 속성만 함께 조회하고, javax.persistence.loadgraph 속성은 엔티티 그래프에 선택한 속성뿐만 아니라 글로벌 fetch 모드가 FetchType.EAGER로 설정된 연관관계까지 함께 조회한다는 차이가 있다.

 

 

 

3. 서브 그래프

- 서브 그래프를 이용하면 엔티티 필드의 하위 연관관계까지 선택할 수 있다.

- @NamedEntityGraph의 subgraphs 속성에 서브 그래프를 지정한다.

- 아래 예시에서는 Order -> OrderItem -> Item 엔티티까지 함께 조회한다.

@NamedEntityGraph(name="Order.withAll",
    attributeNodes={
        @NamedAttributeNode("member"),
        @NamedAttributeNode(value="orderItems", subgraph="orderItems") // List<OrderItem> orderItems
    },
    subgraphs=@NamedSubgraph(name="orderItems", attributeNodes={@NamedAttributeNode("item")}) // Item item
)

 

 

 

4. JPQL에서 엔티티 그래프 사용

- setHint() 메소드로 EntityGraph를 추가한다.

List<Order> resultList = em.createQuery("SELECT o FROM Order o WHERE o.id=:orderId", Order.class)
    .setParameter("orderId", orderId)
    .setHint("javax.persistence.fetchgraph", em.getEntityGraph("Order.withAll"))
    .getResultList();

- JPQL에서 엔티티 그래프를 사용할 때는 항상 SQL 외부 조인을 사용하기 때문에, 만약 SQL 내부 조인을 사용하려면 내부 조인을 명시해야 한다.

SELECT o FROM Order o JOIN FETCH o.member WHERE o.id=:orderId

 

 

5. 동적 엔티티 그래프

- EntityManager.createEntityGraph() 메소드를 사용한다.

public <T> EntityGraph<T> createEntityGraph(Class<T> rootType);

- EntityGraph.addAttributeNodes() 메소드로 연관관계를 엔티티 그래프에 포함한다. 서브 그래프의 경우에는 EntityGraph.addSubgraph() 메소드로 추가하면 된다.

EntityGraph<Order> graph = em.createEntityGraph(Order.class);
graph.addAttributeNodes("member");
Subgraph<OrderItem> orderItems = graph.addSubgraph("orderItems");
orderItems.addAttributeNodes("item");

Map hints = new HashMap();
hints.put("javax.persistence.fetchgraph", graph); // 루트 엔티티 그래프

Order order = em.find(Order.class, orderId, hints);

 

 

 

 

● 참고자료 : 자바 ORM 표준 JPA 프로그래밍

 

반응형

'Spring 사전 준비 > JPA Hibernate' 카테고리의 다른 글

[JPA] 성능 최적화  (0) 2022.08.27
[JPA] JPA 예외 처리  (0) 2022.08.25
[JPA] JPA 리스너  (0) 2022.08.24
[JPA] Entity와 Table간의 데이터 타입 변환  (0) 2022.08.24
[JPA] JPA와 컬렉션  (0) 2022.08.24

댓글