使用 JPQL/EntitGraph 加载子实体不适用于 EclipseLink 和 spring 数据

Load subentities with JPQL/EntitGraph is not working with EclipseLink and spring data

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

@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 ...

如果我使用 queryhints 那么它可以与 subselect 一起使用,那有什么问题吗? https://www.eclipse.org/eclipselink/documentation/2.5/jpa/extensions/q_left-join-fetch.htm

在休眠模式下效果很好。

您会注意到 EclipseLink 总是对任何关系映射执行额外的查询,除非您指定 fetchJoin 注释(或查询提示,或使用自定义程序修改映射)告诉它要做什么,这与关系被渴望或懒惰地获取。另一方面,Hibernate 将所有渴望访问解释为使用 join。没有必要争论哪个更好 - 它们是视情况而定的,并且有充分的理由将任一解决方案作为通用解决方案。

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