延迟加载孩子,里面有急切的集合

Posted

技术标签:

【中文标题】延迟加载孩子,里面有急切的集合【英文标题】:Lazy loading children, that have eager collections inside 【发布时间】:2015-07-29 20:18:14 【问题描述】:

我对以下实体有疑问:森林、树木、树叶。正如你可以想象的那样,一片森林可以有很多树,而一棵树有很多叶子。

我想延迟加载森林中的所有树木并急切地加载树木的所有叶子。我的带有休眠注释的代码如下所示:

Forest.java

@Entity
@Table(name = "Forests")
public class Forest implements Comparable<Forest> 

      @Id
      @Column(name = "forestnumber", length=10, nullable=false)
      private String number;

      @OneToMany(fetch=FetchType.LAZY, mappedBy="forest")
      private Set<Tree> trees = null;

      // some other attributes and methods

Tree.java

 @Entity
 @Table(name = "Trees")
 public class Tree implements Comparable<Tree> 

        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name="tree_id", nullable=false)
        private int id;

        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "forestnumber", nullable = false)
        @Fetch(FetchMode.JOIN)
        private Forest forest;

        @OneToMany(fetch=FetchType.EAGER, mappedBy="tree")
        @Fetch(FetchMode.JOIN)
        private Set<Leaf> leafs = null;

        // some other attributes and methods

Leaf.java

 @Entity
 @Table(name = "Leafs")
 public class Leaf implements Comparable<Leaf> 

        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name="leaf_id", nullable=false)
        private int id;

        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "tree_id", nullable = false)
        @Fetch(FetchMode.JOIN)
        private Tree tree;

        // some other attributes and methods

我的问题:加载森林并调用 getTrees() 方法会导致一组 select 语句。 Hibernate 执行一条语句来获取所有树,并为每棵树执行第二条语句以收集所有叶子。 在我看来,hibernate 应该只生成一个语句,使用连接来同时收集树木和树叶。

谁能告诉我问题的原因以及如何解决? 非常感谢!

顺便说一句:如果我将森林树的获取策略更改为 EAGER,则一切正常,只需一条语句。

【问题讨论】:

【参考方案1】:

你可以尝试初始化

Hibernate.initialize(forestInstance);

或者编写一个带有 fetch 的连接查询来急切地检索所有的孩子。

另见

Is there a way to change the JPA fetch type on a method?

【讨论】:

【参考方案2】:

删除 fetch=FetchType.EAGER。 Eager fetching 触发级联 select 语句。

【讨论】:

感谢您的回答。叶子应该急切地取来。但是,我不想为每棵树选择语句,而是希望只有一个带有连接的选择。如您所见,我使用@Fetch Annotation 来告诉hibernate 使用JOIN。但这只有在我也急切地加载森林树木的情况下才有效。为什么? 尝试从叶子集合下的 @OneToMany(fetch=FetchType.EAGER, mappedBy="tree") 中删除 fetch=FetchType.EAGER 以解决您的问题 从@OneToMany 中移除 fetch=FetchType.EAGER(fetch=FetchType.EAGER, mappedBy="tree") 没有帮助

以上是关于延迟加载孩子,里面有急切的集合的主要内容,如果未能解决你的问题,请参考以下文章

实体框架急切加载不返回数据,延迟加载有

何时在休眠中使用延迟加载/急切加载?

EF急切加载和延迟加载的区别?

远程案例中的延迟/急切加载策略(JPA)

什么是Hibernate中的延迟加载?

LINQ中的First()会导致急切或延迟加载吗?