【问题标题】:Hibernate: Initialize all children with a single join statement in HQL / QueryDSL?Hibernate:在 HQL / QueryDSL 中使用单个连接语句初始化所有子级?
【发布时间】:2012-06-26 19:14:55
【问题描述】:

我们现在正在使用 QueryDSL 进行数据库查询,但我认为这个问题更普遍地与休眠相关..

我想知道:HQL 是否将我查询的实体放入休眠上下文/缓存中,以便可以从那里访问它们?我在想,如果我为一个实体运行一个大的leftjoin,显式收集所有子关系,如果我可以告诉休眠在将结果映射到我的实体时使用该信息,我应该能够节省延迟加载目的。我就是想不通。。

示例: A有Bs,B有Cs。现在,如果我为某个 A 构建查询到 fetch all 并将其与 Bs 和 Cs 连接(查询 DSL 实现):

List<A> as = query.from(QA.a).leftJoin(QA.a.b,QB.b).leftJoin(QB.b.c,QC.c).where(a.id.eq("1)).fetchAll();

我会得到一个很好的 SQL 语句,上面写着

select... from A inner join B ... inner join C ... where ...

所以结果应该足以让hibernate初始化

as.get(index).getBs()
as.get(index).getBs().get(index).getCs()

但它不会这样做,而是会运行查询

select ...  from B where B.aId = ??

是否有可能通过初始化一个包含所有子节点的实体来减少这些延迟加载,还是我希望太多?

如果我通过连接加载所有数据,休眠会将它们保存在其缓存中,并且它会访问该缓存以进行那些延迟加载还是会轮询数据库?我对此有发言权还是完全不在我的掌控之中?

谢谢@大家!

【问题讨论】:

    标签: java hibernate jpa hql querydsl


    【解决方案1】:

    在 HQL 查询中,您需要使用 fetch 关键字来执行此操作:

    select a from A a left join fetch a.cs b left join fetch b.cs where ...
    

    这在Hibernate documentation中有很好的解释。

    我没用过QueryDSL,但是根据its documentation,你只需要在每次join后调用fetch()方法添加这个fetch关键字即可:

    query.from(QA.a).leftJoin(QA.a.b,QB.b).fetch().leftJoin(QB.b.c,QC.c).fetch().where...
    

    【讨论】:

      【解决方案2】:

      对不起,我忘了在我的帖子中提到这一点。我确实尝试过使用fetch,但没有成功。原来解决方案是使用

      @Fetch(FetchMode.JOIN)
      

      在实体属性处。

      【讨论】:

      • 您是否尝试过不使用别名参数的 leftJoin / fetch?
      • 不,没试过。如果我不使用别名,源代码和查询会膨胀......但我会试一试。我根据关系使用innerJoin 和leftJoin。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多