【问题标题】:Hibernate criteria setFetchMode gets ignored using projections使用投影忽略休眠条件 setFetchMode
【发布时间】:2018-11-17 19:58:31
【问题描述】:

我试图急切地获取所有 contentItems 以避免 N + 1 延迟初始化问题,但我的 setfetchmode 调用在使用投影时被休眠忽略。虽然不使用投影,但它按预期工作。

我做错了什么?

contentItem 是一个自定义对象。

Session session = getSessionFactory().getCurrentSession();
    Criteria criteria = session.createCriteria(Media.class);
    criteria
        .setProjection(Projections.projectionList()
          .add(Projections.property("id"), "id")
          .add(Projections.property("fileName"), "fileName")
          .add(Projections.property("mimeType"), "mimeType")
          .add(Projections.property("contentItem"), "contentItem"))
        .setFetchMode("contentItem", FetchMode.JOIN)
        .setResultTransformer(Transformers.aliasToBean(Media.class));
    criteria.addOrder(Order.asc("id"));
    criteria.setFirstResult(firstResult);
    criteria.setMaxResults(maxResults);
    return criteria.list();

更新:除了@NiVeR 答案

实体关系获取类型仍然对结果没有影响。

private ContentItem contentItem;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "content_item_id")
public ContentItem getContentItem() {
    return this.contentItem;
}

像这样重新定位 setFetchMode 也没有效果。

Session session = getSessionFactory().getCurrentSession();
Criteria criteria = session.createCriteria(Media.class);
criteria.setFetchMode("contentItem", FetchMode.JOIN);
criteria
    .setProjection(Projections.projectionList()
      .add(Projections.property("id"), "id")
      .add(Projections.property("fileName"), "fileName")
      .add(Projections.property("mimeType"), "mimeType")
      .add(Projections.property("contentItem"), "contentItem"))
    .setResultTransformer(Transformers.aliasToBean(Media.class));
criteria.addOrder(Order.asc("id"));
criteria.setFirstResult(firstResult);
criteria.setMaxResults(maxResults);
return criteria.list();

【问题讨论】:

  • 那么,如果你去掉投影,它会起作用吗?它没有给出 n+1 问题?
  • 没错,它在移除投影时不会出现 n+1 问题。

标签: hibernate fetch criteria hibernate-criteria nhibernate-projections


【解决方案1】:

可能行为是由以下行解释的:

.add(Projections.property("contentItem"), "contentItem"))

此时为了投影该实体的关系,Hibernate 使用定义关系的实体中定义的 FetchType。因此,您之后添加的 FetchMode.JOIN 没有影响,因为它会在以后发生。

【讨论】:

  • 我已经尝试在早期状态下添加 setfetchmode,但它没有效果,并且实体中定义的 fetchType 是渴望获取。我将使用实体及其关系进行编辑。不过谢谢!
  • 还有一点就是投影应该在join之后进行。
  • 查看更新。还是没有效果。它仍然以某种方式被忽略。
  • @Merv 您不应该在实体级别使用@ManyToOne(fetch = FetchType.EAGER),因为您可能会陷入巨大的实体图加载。您应该将其 LAZY 留在那里,并使用查询(正如您所做的那样)仅针对该特定查询覆盖连接类型,因为您知道要加载所有数据。
  • 我试着把它放到@ManyToOne(fetch = FetchType.LAZY) 但还是一样。它仍然给我这个休眠查询: Hibernate: select this_.id as y0_, this_.file_name as y1_, this_.mime_type as y2_, this_.content_item_id as y3_ from development.media this_ order by y0_ asc limit ? .仍然没有像我预期的那样加入。
猜你喜欢
  • 2014-09-17
  • 2014-11-08
  • 2011-04-22
  • 1970-01-01
  • 2011-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-08
相关资源
最近更新 更多