【问题标题】:Hibernate fetch eager association when query for lazy oneHibernate 在查询惰性时获取渴望关联
【发布时间】:2014-09-29 01:02:52
【问题描述】:

我有一个常见的父子关系,例如:

class Parent {
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    List<ChildOne> childrenOne;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    List<ChildTwo> childrenTwo;

    @OneToMany
    List<LazyChild> lazyChildren;

    @Id
    Long id;
}

然后我有 HQL 查询,如:

select lazyChild from Parent p 
join p.lazyChildren lazyChild
where p.id = ? and lazyChild.mnemonic='AAA'

当我执行它时,我得到了 LazyChild 对象,这就是我想要的。但是hibernate也会初始化所有急切定义的集合,这是我不想要的。 hibernate 单独调用来获取热切的关联并不直观。我通过切换到显示 SQL 查询来看到它。

如何避免不必要的 SQL 调用?

【问题讨论】:

    标签: hibernate hql


    【解决方案1】:

    通过指定FetchType.EAGER,您已经对 Hibernate 说,每次它加载父对象时,您希望它加载那些子对象。如果您不希望发生这种情况,则不能指定 Eager fetch 类型。

    Hibernate 不够聪明,无法知道当您查询Parent 时,您只需要lazyChild。它只知道你已经向Parent 对象发出了请求,所以它需要加载急切地获取子对象。

    如果您是 Hibernate 新手,您可能会发现我的教程 here 很有帮助。

    【讨论】:

    • 我对休眠并不陌生,但它有一个我不太了解的部分。我花了一些时间调试并找到调用 doQueryAndInitializeNonLazyCollections 的方法:)。看起来你是对的。在查询中使用 Parent 时,Hibernate 将始终初始化急切的集合。但从 SQL 的角度来看,这并不是最优的解决方案。
    【解决方案2】:

    我不确定我是否理解您想要做什么。 但是,如果您不希望您的集合 childrenOnechildrenTwo 被加载,您可能应该使用 FetchType.LAZY 声明它们。

    在我看来,您没有查询正确的实体,如果您只想要LazyChild 的列表,那么您的 HQL 应该是这样的:

    from LazyChild child
    where child.parent.id = ? and child.mnemonic='AAA'
    

    假设您在 LazyChild 实体中映射了父级:

    @ManyToOne //(fetch=FetchType.LAZY) if you don't need to have the parent loaded
    @JoinColumn(name = "parent_id")
    private Parent parent;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-20
      • 2012-09-08
      • 2011-04-28
      • 2013-10-04
      • 1970-01-01
      • 2014-03-13
      • 2019-02-02
      • 2016-08-17
      相关资源
      最近更新 更多