はじめに
JPA の EntityGraph
を使うことで、クエリーで取得する対象をカスタマイズすることができます。
同じ Entity から様々なデータの見せ方が必要で、パフォーマンスの為に最小限のデータセットのみを取得したい場合などに EntityGraph
が役に立ちます。
詳しくは以下を参照してください。
EntityGraph
を EntityManager
から操作する場合は以下のようになります。
EntityGraph<Employee> graph = em.createEntityGraph(Employee.class); graph.addSubgraph(Employee_.address).addAttributeNodes(Address_.city); TypedQuery<Employee> query = em.createQuery(...); query.setHint("jakarta.persistence.loadgraph", graph); List<Employee> results = query.getResultList();
addSubgraph()
で同じサブグラフを追加した場合は、後勝ちとなります。
つまり以下のように addSubgraph()
を登録した場合は Address_.city
のノードはフェッチ対象に含まれなくなります。
EntityGraph<Employee> graph = em.createEntityGraph(Employee.class);
graph.addSubgraph(Employee_.address).addAttributeNodes(Address_.city);
graph.addSubgraph(Employee_.address).addAttributeNodes(Address_.street);
以下のようにするか、
EntityGraph<Employee> graph = em.createEntityGraph(Employee.class);
Subgraph<Address> subgraph = graph.addSubgraph(Employee_.address);
subgraph.addAttributeNodes(Address_.city);
subgraph.addAttributeNodes(Address_.street);
以下のようにすることになります。
subgraph.addAttributeNodes(Address_.city, Address_.street);
しかし、フェッチ範囲を以下のように部品として適用したい場合には少し困ります。
Consumer<EntityGraph<Employee>> foo = graph -> graph.addSubgraph(Employee_.address).addAttributeNodes(Address_.city); Consumer<EntityGraph<Employee>> foo = graph -> graph.addSubgraph(Employee_.address).addAttributeNodes(Address_.street);
EntityGraph からの Subgraph 取得
以下のように EntityGraph に登録済みの Subgraph を抽出することができます。
public static <T, Y> Subgraph<Y> subgraph(EntityGraph<T> graph, Attribute<? super T, Y> attr, Class<Y> clazz) { return graph.getAttributeNodes().stream() .filter(node -> node.getAttributeName().equals(attr.getName())) .map(node -> node.getSubgraphs().get(clazz)) .filter(Objects::nonNull) .findFirst() .orElseGet(() -> graph.addSubgraph(attr.getName(), clazz)); }
以下のようにすれば、必要なものを適宜組み合わせてフェッチ戦略を使っていくことができます。
Consumer<EntityGraph<Employee>> foo = graph -> subgraph(graph, Employee_.address, Address.class).addAttributeNodes(Address_.city); Consumer<EntityGraph<Employee>> foo = graph -> subgraph(graph, Employee_.address, Address.class).addAttributeNodes(Address_.street);
以上、需要の無い話でした。
以下も合わせて参照ください。