首页 > 解决方案 > 使用 JPQL/EntitGraph 加载子实体不适用于 EclipseLink 和 spring 数据

问题描述

我正在尝试使用 EntityGraphs 或 JPQL 创建 1 个选择,而不是许多小(子)选择。但是,在额外的选择中加载了子实体。例子:

@NamedEntityGraph( name = "All",
                   attributeNodes = {
                         @NamedAttributeNode( value = "bars", subgraph = "subgraph.foobars") },
                         subgraphs = {
                         @NamedSubgraph( name = "subgraph.foobars",
                                         attributeNodes = {
                                               @NamedAttributeNode(value = "fooBars", subgraph = "subgraph.foobar"),
                                               @NamedAttributeNode( "mqttEndpoints" ) } ),
                         @NamedSubgraph( name = "subgraph.foobar",
                                         attributeNodes = {
                                               @NamedAttributeNode( "name" ) } ) })

public class Foo {
   @OneToMany( fetch = FetchType.LAZY )
   private Set<Bar> bars = Sets.newHashSet();
}

public class Bar {
   @OneToMany( fetch = FetchType.LAZY )
   private Set<FooBar> fooBars = Sets.newHashSet();
}

public class FooBar {
   String name;
}

   @EntityGraph( value = "All", type = EntityGraph.EntityGraphType.FETCH )
   Optional<Foo> findById( String id);

      @Query( "SELECT DISTINCT f FROM foo f"
                 + " LEFT JOIN FETCH f.bar bars "
                 + " LEFT JOIN FETCH bar.fooBars foobars "
                 + " WHERE t.id =:id " )
   Optional<Foo> readById( String id);

日志

SELECT ...
FROM foo t1 
LEFT OUTER JOIN bars t0 ON (t0.bar_id = t1.id) 


SELECT name
FROM foobar 
WHERE ...

如果我使用查询提示,那么它可以与子选择一起使用,那么出了什么问题? https://www.eclipse.org/eclipselink/documentation/2.5/jpa/extensions/q_left-join-fetch.htm

使用休眠,这很好用。

标签: spring-data-jpaspring-dataeclipselink

解决方案


您会注意到 EclipseLink 总是对任何关系映射进行额外查询,除非您指定 fetchJoin 注释(或查询提示,或使用定制器修改映射)告诉它要做什么,这与关系是否急切或懒惰无关获取。另一方面,Hibernate 解释所有使用 join 的渴望访问。没有必要争论哪个更好 - 它们是情境性的,有充分的理由将任何一种解决方案作为通用解决方案。

这意味着,如果您想要与 EclipseLink 即时连接,您必须做的不仅仅是指出需要急切地获取关系,并包括在查询提示中。如果您要使用提取图来优化事物,那么查看其他提取类型(例如批量提取)可能会有所帮助。额外的查询/语句对性能并不总是坏事,尤其是随着对象图的增长。数据库将被迫返回 N*M 重复的 Foo 数据行,结果中的每个 Bar 和 FooBar 组合一个。根据数据大小,在某个点上,让子项进入单独的查询会更有效。


推荐阅读