【问题标题】:Prevent Hibernate N+1 Selects when grouping by an entity按实体分组时防止休眠 N+1 选择
【发布时间】:2010-12-02 00:14:08
【问题描述】:

我有一个这样构建的 Hibernate Criteria 对象:

Criteria obsCriteria = hibernateTemplate.getSessionFactory()
  .getCurrentSession().createCriteria(Observation.class);

ProjectionList projection = Projections.projectionList()
  .add(Projections.rowCount())
  .add(Projections.avg("value").as("avgScore"))
  .add(Projections.avg("type.score"))
  .add(Projections.max("date"))
  .add(Projections.groupProperty("observedSubject"));
criteria.setProjection(projection);

这为我产生了正确的结果,但“observedSubject”属性是一个实体。当我将 set show_sql 设置为 true 时,我看到在第一个查询(返回 18 行)之后,有 18 个选择来获取observedSubject 实体。我试过了:

criteria.setFetchMode("observedSubject", FetchMode.JOIN);

但这没有用。作为一种在黑暗中的刺,我尝试了:

criteria.createAlias("observedSubject", "observedSubject", Criteria.FULL_JOIN);

但这也没有用。有什么办法可以防止这种行为?

【问题讨论】:

    标签: hibernate hibernate-criteria


    【解决方案1】:

    您是否将observedSubject 注释为FetchType.LAZY?如果没有,Hibernate 将恢复到默认行为,即EAGER fetching。

    如果您确实希望在运行时获取子关联,但不想为每个关联单独调用SELECT,请在关联上设置@BatchSize,Hibernate 将批处理@987654326 @ 调用,让事情变得更高效。

    【讨论】:

    • 感谢您尝试回答这个令人费解的问题。我确实需要 ObservedSubject 中的数据——这就是它被添加到投影列表的原因。我尝试了您建议的 @BatchSize 注释,但我认为它不会适用于使用 Criteria API 的此类查询,是吗?我想到的一种方法是创建一个包含我想要的所有连接的视图(包括来自观察主题的字段)并基于该视图创建一个不可变实体。这节省了 N+1 个查询,但它与我之前尝试的不太接近,所以我仍然想知道是否有办法做到这一点。
    • 是的,@BatchSize 确实适用于条件查询。我在 Get 方法上为子关联设置了“@BatchSize(size=16)”,Hibernate 在获取子关联时使用了IN(16 组)而不是=。方法是先获取父母,然后循环列表,获取孩子:for(Parent p : parents) { if(p.getChildren() != null) { p.getChildren().size(); // forces the load } }
    • 您评论的第一部分听起来像我想要的,但我对最后一部分感到困惑。 'N+1' 中的 'N' 是这种情况下父母的数量,所以如果我必须遍历父母,它仍然会执行 N+1 查询(这是我申请后的样子@BatchSize)。
    • 也许我很困惑。您的原始帖子听起来像是您想加载子关联,但不想为每个父对象单独调用 SQL,这就是我推荐 BatchSize 的原因。我的理解有误吗?
    • 我可能对我上次的评论感到困惑,但这并不是真正的亲子关系。我按observedSubject 分组,因此每行返回一个observedSubject。但是,当我运行查询时,它会返回所有行,然后每行获取一次 observedSubject(一个 Person 实体)。
    猜你喜欢
    • 2010-10-09
    • 2020-02-14
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    • 2011-10-04
    • 2011-11-22
    • 1970-01-01
    相关资源
    最近更新 更多