Close
Close full mode
logo만렙 개발자 키우기

(4) 엔티티 그래프

Git RepositoryEdit on Github
Last update: a year ago by nowwaterReading time: 2 min

1. 글로벌 페치 조인

  • @ManyToOne(fetchType.EAGER) 또는 @ManyToOne(fetchType.LAZY) 를 사용
  • 애플리케이션 전체에 영향을 주고 변경할 수 없는 단점이 있다.
  • 일반적으로 글로벌 fetch 옵션은 fetchType.LAZY를 사용하고, 엔티티를 조회할 때 연관된 엔티티를 함께 조회할 필요가 있으면 JPQL 페치 조인을 사용한다.

2. JPQL 패치 조인

  • select o from Order o join fetch o.member

=> 같은 JPQL을 중복해서 작성하는 경우가 많다. ex) Order 와 OrderItem, Order 와 Member...

따라서 엔티티 그래프 기능을 사용한다.

3. 엔티티 그래프

  • 엔티티 조회 시점에 연관된 엔티티들을 함께 조회하는 기능이다.

14.4.1 Named 엔티티 그래프

  • @NamedEntityGraph 로 정의한다.

    • name : 엔티티 그래프의 이름을 정의한다.

    • attributeNodes : 함께 조회할 속성 선택.

    • ex)

      @NamedEntityGraph(name = "Order.withMember", attributeNodes = { @NamedAttributeNode("member") })
      @Entity
      @Table(name = "ORDERS")
      public class Order { ... }
    • 이 엔티티 그래프를 사용하면 Order를 조회할 때 연관된 member도 함께 조회할 수 있다.


14.4.2 em.find() 에서 엔티티 그래프 사용

EntityGraph graph = em.getEntityGraph("Order.withMember"); // 엔티티 그래프 획득
Map Hints = new HashMap();
hints.put("javax.persistence.fetchgraph", graph);
Order order = em.find(Order.class, orderId, hints);
  • 엔티티 그래프는 JPA의 힌트 기능을 사용해서 동작한다.
  • 힌트의 키로 javax.persistence.fetchgraph 를 사용하고, 힌트의 값으로 찾아온 엔티티 그래프를 사용하면 된다.

14.4.3 subgraph

ex) Order -> OrderItem -> Item 을 조회할 경우

Item은 Order가 관리하는 필드가 아니지만 subgraph를 통해 사용 가능

@NamedEntityGraph(name = "Order.withAll", attributeNodes = {
@NamedAttributeNode("member"),
@NamedAttributeNode(value = "orderItems", subgraph = "orderItems")},
subgraphs = @NamedSubgraph(name = "orderItems", attributeNodes = { // 여기서는 서브그래프의 이름을 orderItems 라고 지정한 것
@NamedAttributeNode("item")
})
)
@Entity
@Table(name="ORDERS")
public class Order{ ... }

14.4.4 JPQL 에서 엔티티 그래프 사용

em.find() 와 동일하게 힌트만 추가하면 된다.

List<Order> resultList =
em.createQuery("select o from Order o where o.id = :orderId", Order.class)
.setParameter("orderId", orderId)
.setHint("javax.persistence.fetchgraph", "em.getEntity("Order.withAll"))
.getResultList();

14.4.5 동적 엔티티 그래프

public <T> EntityGraph<T> createEntityGraph(Class<T> rootType); 메소드 사용

EntityGraph<Order> graph = em.createEntityGraph(Order.claass); // 동적 엔티티 그래프 생성
graph.addAttributeNodes("member"); // Order.member 속성을 엔티티 그래프에 포함
subgraph<OrderItem> orderItems = graph.addSubgraph("orderItems"); // 서브 그래프 포함
orderItems.addAttributeNodes("item"); // 서브 그래프가 item 속성 포함
Map hints = new HashMap();
hints.put("javax.persistence.fetchgraph", graph);
Order order = em.find(Order.class, orderId, hints);

14.4.6 엔티티 그래프 정리

  • 엔티티 그래프는 항상 조회하는 엔티티의 ROOT 에서 시작해야 한다.
  • 이미 로딩된 엔티티는 엔티티 그래프가 적용되지 않는다. (아직 초기화되지 않은 프록시에는 엔티티 그래프가 적용됨)
Order order1 =em.find(Order.class, orderId);
hints.put("javax.persistence.fetchgraph", em.getEntityGraph("Order.withMember"));
Order order2 =em.find(Order.class, orderId, hints); // order1 과 같은 인스턴스 반환
  • javax.persistence.fetchgraph : 선택한 속성만 함께 조회

  • javax.persistence.loadgraph : 엔티티 그래프에 선택한 속성 + 글로벌 fetch 모드가 FetchType.EAGER 로 설정된 연관관계 포함 조회

내 정리

엔티티 자체에 Named 엔티티 그래프를 설정해두고, 조회하는 방법은 3가지가 존재한다.

  1. hint + em.find()

  2. JPQL 에서 .setHint("javax.persistence.fetchgraph", em.getEntityGraph("Order.withAll"))

  3. 동적 엔티티 그래프

🚀 JPA — Previous
(3) 리스너
Next — 🚀 JPA
15장. 고급 주제와 성능 최적화