(4) 엔티티 그래프
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가지가 존재한다.
hint + em.find()
JPQL 에서
.setHint("javax.persistence.fetchgraph", em.getEntityGraph("Order.withAll"))
동적 엔티티 그래프