首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Hibernate Criteria使用FetchType.EAGER多次返回子对象

Hibernate Criteria使用FetchType.EAGER多次返回子对象
EN

Stack Overflow用户
提问于 2010-01-03 22:11:49
回答 8查看 80.4K关注 0票数 120

我有一个包含OrderTransactions列表的Order类,并将其映射为一个一对多的Hibernate映射,如下所示:

@OneToMany(targetEntity = OrderTransaction.class, cascade = CascadeType.ALL)
public List<OrderTransaction> getOrderTransactions() {
    return orderTransactions;
}

这些Order还有一个字段orderStatus,用于根据以下条件进行筛选:

public List<Order> getOrderForProduct(OrderFilter orderFilter) {
    Criteria criteria = getHibernateSession()
            .createCriteria(Order.class)
            .add(Restrictions.in("orderStatus", orderFilter.getStatusesToShow()));
    return criteria.list();
}

这是可行的,结果和预期的一样。

下面是我的问题:为什么当我显式地将fetch类型设置为EAGER时,Order会在结果列表中多次出现?

@OneToMany(targetEntity = OrderTransaction.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public List<OrderTransaction> getOrderTransactions() {
    return orderTransactions;
}

我必须如何更改我的标准代码才能达到与新设置相同的结果?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2010-01-03 23:15:55

如果我正确理解了您的配置,这实际上是预期的行为。

在任何结果中都会得到相同的Order实例,但是由于现在您正在使用OrderTransaction进行连接,因此它必须返回与常规sql连接相同数量的结果

所以实际上它应该出现多次。作者(Gavin King)本人here很好地解释了这一点:它既解释了原因,也解释了如何仍然获得明显的结果

在Hibernate FAQ中也提到:

对于为集合启用了外部连接获取的查询,

Hibernate不会返回distinct结果(即使我使用了distinct关键字)?首先,您需要了解SQL以及外连接在SQL中是如何工作的。如果您不能完全理解和理解SQL中的外部连接,请不要继续阅读本常见问题解答,而应参考SQL手册或教程。否则,您将无法理解下面的解释,并且您将在Hibernate论坛上抱怨此行为。

可能返回相同Order对象的重复引用的典型示例:

List result = session.createCriteria(Order.class) .setFetchMode("lineItems",FetchMode.JOIN) .list();

..。

List result = session.createCriteria(Order.class) .list();List result = session.createQuery("select o from Order O left join fetch o.lineItems").list();

所有这些示例都会生成相同的SQL语句:

SELECT o.*,l.* from ORDER O LEFT OUTER JOIN LINE_ITEMS l ON o.ID = l.ORDER_ID

想知道为什么会有重复的东西吗?查看SQL结果集,Hibernate不会在外部连接结果的左侧隐藏这些重复项,而是返回驱动表的所有重复项。如果数据库中有5个订单,并且每个订单有3个行项目,则结果集将为15行。这些查询的Java结果列表将有15个元素,它们的类型都是Order。Hibernate只会创建5个Order实例,但SQL结果集的副本将保留为对这5个实例的重复引用。如果您不理解这最后一句话,您需要阅读Java以及Java堆上的实例和对此类实例的引用之间的区别。

(为什么是左外部连接?如果您有一个没有行项目的额外订单,结果集将是16行,右侧填充为空,其中行项目数据用于其他订单。即使他们没有行项目,你也想要订单,对吧?如果没有,请在HQL中使用内部连接获取)。

默认情况下,Hibernate不会过滤掉这些重复的引用。有些人(而不是你)实际上想要这样。你怎么过滤掉它们呢?

如下所示:

采集结果=新的LinkedHashSet( session.create*(...).list() );

票数 124
EN

Stack Overflow用户

发布于 2010-01-04 18:46:44

除了Eran提到的之外,另一种获得你想要的行为的方法是设置结果转换器:

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
票数 93
EN

Stack Overflow用户

发布于 2014-04-07 23:05:36

试一试

@Fetch (FetchMode.SELECT) 

例如

@OneToMany(targetEntity = OrderTransaction.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@Fetch (FetchMode.SELECT)
public List<OrderTransaction> getOrderTransactions() {
return orderTransactions;

}

票数 42
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1995080

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档