hibernate在sessionfactory创建期间引发此异常:
org.hibernate.loader.multiplebagfetchexception:无法同时提取多个行李
这是我的测试用例:
父.java
@Entity
public Parent {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
// @IndexColumn(name="INDEX_COL") if I had this the problem solve but I retrieve more children than I have, one child is null.
private List<Child> children;
}
子.java
@Entity
public Child {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@ManyToOne
private Parent parent;
}
这个问题怎么样?我能做什么?
编辑
好吧,我的问题是另一个“父”实体在我的父实体中,我的真实行为是:
父.java
@Entity
public Parent {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@ManyToOne
private AnotherParent anotherParent;
@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
private List<Child> children;
}
其他父级.java
@Entity
public AnotherParent {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
private List<AnotherChild> anotherChildren;
}
hibernate不喜欢有两个集合 FetchType.EAGER
,但这似乎是一个错误,我没有做不寻常的事情。。。
正在删除 FetchType.EAGER
从 Parent
或者 AnotherParent
解决了问题,但我需要它,所以真正的解决办法是使用 @LazyCollection(LazyCollectionOption.FALSE)
而不是 FetchType
(感谢波佐的解决方案)。
15条答案
按热度按时间lo8azlld1#
对我来说,问题是有嵌套的急切回迁。
一种解决方案是将嵌套字段设置为lazy,并使用hibernate.initialize()加载嵌套字段:
ruoxqz4g2#
我认为hibernate的更新版本(支持jpa2.0)应该可以处理这个问题。但除此之外,您可以通过使用以下内容注解集合字段来解决此问题:
请记住移除
fetchType
属性@*ToMany
注解。但请注意,在大多数情况下
Set<Child>
比…更合适List<Child>
,所以除非你真的需要List
-追求Set
但要提醒的是,使用集合并不能消除vlad mihalcea在回答中描述的笛卡尔积!llycmphe3#
我们尝试了set而不是list,这是一个噩梦:当您添加两个新对象时,equals()和hashcode()无法区分它们!因为他们没有身份证。
像eclipse这样的典型工具从数据库表生成这种代码:
您也可以阅读这篇文章,它正确地解释了jpa/hibernate是多么混乱。读完这篇文章,我想这是我生命中最后一次使用orm。
我也遇到过领域驱动的设计人员,他们基本上说orm是一件可怕的事情。
sxissh064#
要解决它只需
Set
代替List
对于嵌套对象。别忘了使用
fetch=FetchType.EAGER
会有用的。还有一个概念
CollectionId
在hibernate中,如果您只想使用列表。但要提醒的是,你不会消除下面的笛卡尔积所描述的弗拉德米哈尔恰在他的答案!
umuewwlo5#
当您的saveral集合对象太复杂时,最好使用lazy,当您确实需要加载集合时,请使用:
Hibernate.initialize(parent.child)
获取数据。slmsl1lt6#
您可以使用新注解来解决此问题:
实际上,fetch的默认值也是fetchtype.lazy。
w41d8nur7#
只是从
List
键入到Set
类型。但要提醒的是,你不会消除下面的笛卡尔积所描述的弗拉德米哈尔恰在他的答案!
svmlkihl8#
在代码中添加特定于hibernate的@fetch注解:
这应该可以解决与hibernate bug hhh-1718相关的问题
r6l8ljro9#
评论两者
Fetch
以及LazyCollection
有时有助于运行项目。wz3gfoph10#
在尝试了本文和其他文章中描述的每一个选项之后,我得出的结论是,解决方法如下。
在任何地方@
XXXToMany(mappedBy="parent", fetch=FetchType.EAGER)
之后不久这对我有用
bvpmtnay11#
有件好事
@LazyCollection(LazyCollectionOption.FALSE)
有几个带此注解的字段可以同时存在FetchType.EAGER
不能,即使在这种共存是合法的情况下。例如,一个
Order
可能有一份OrderGroup
(一个简短的)以及Promotions
(也很短)。@LazyCollection(LazyCollectionOption.FALSE)
可用于两个,而不会引起LazyInitializationException
都不是MultipleBagFetchException
.对我来说
@Fetch
解决了我的问题吗MultipleBacFetchException
但随后导致LazyInitializationException
,臭名昭著的no Session
错误。zvokhttg12#
我发现了一篇关于hibernate在这种对象Map中的行为的博文:http://blog.eyallupu.com/2010/06/hibernate-exception-simultaneously.html
mxg2im7a13#
您可以在jpa中保存列表,并向其中至少一个列表添加jpa annotation@ordercolumn(显然是要排序的字段的名称)。不需要特定的hibernate注解。但请记住,如果所选字段没有从0开始的值,它可能会在列表中创建空元素
在children中,您应该添加orderindex字段
gojuced714#
考虑到我们有以下实体:
你想找个家长来吗
Post
实体以及所有comments
以及tags
收藏。如果您使用多个
JOIN FETCH
指令:hibernate将抛出臭名昭著的:
hibernate不允许获取多个包,因为这样会生成笛卡尔积。
最糟糕的“解决方案”
现在,你会发现许多答案、博客文章、视频或其他资源告诉你使用
Set
而不是List
为您的收藏。那是个糟糕的建议。别那么做!
使用
Sets
而不是Lists
将使MultipleBagFetchException
走开,但笛卡尔积仍然存在,这实际上更糟,因为在应用这个“修复”很久之后,您就会发现性能问题。正确的解决方案
您可以执行以下操作:
在第一个jpql查询中,
distinct
不转到sql语句。这就是为什么我们要设定PASS_DISTINCT_THROUGH
jpa查询提示false
.distinct在jpql中有两种含义,在这里,我们需要它来消除
getResultList
在java方面,而不是sql方面。只要你使用
JOIN FETCH
,你会没事的。通过使用多个查询,您将避免使用笛卡尔积,因为除了第一个集合之外的任何其他集合都是使用辅助查询获取的。
你还可以做更多
如果你用的是
FetchType.EAGER
Map时的策略@OneToMany
或者@ManyToMany
联想,那么你很容易就有了MultipleBagFetchException
.你最好还是从
FetchType.EAGER
至Fetchype.LAZY
因为急于获取是一个可怕的想法,可能会导致关键的应用程序性能问题。结论
避免
FetchType.EAGER
不要从List
至Set
只是因为这样做会让冬眠隐藏MultipleBagFetchException
在地毯下面。一次只取一件收藏品,你就没事了。只要在初始化集合时使用相同数量的查询,就可以了。只是不要在循环中初始化集合,因为这将触发n+1查询问题,这也会影响性能。
nfeuvbwi15#
在我的结尾,当我有多个fetchtype.earge集合时发生了这种情况,如下所示:
此外,这些集合在同一列上连接。
为了解决这个问题,我将其中一个集合更改为fetchtype.lazy,因为它适合我的用例。
祝你好运~j