可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Hibernate throws this exception during SessionFactory creation:
org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
This is my test case:
Parent.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;
}
Child.java
@Entity
public Child {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@ManyToOne
private Parent parent;
}
How about this problem? What can I do?
EDIT
OK, the problem I have is that another \"parent\" entity is inside my parent, my real behavior is this:
Parent.java
@Entity
public Parent {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@ManyToOne
private AntoherParent anotherParent;
@OneToMany(mappedBy=\"parent\", fetch=FetchType.EAGER)
private List<Child> children;
}
AnotherParent.java
@Entity
public AntoherParent {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy=\"parent\", fetch=FetchType.EAGER)
private List<AnotherChild> anotherChildren;
}
Hibernate doesn\'t like two collections with FetchType.EAGER
, but this seems to be a bug, I\'m not doing unusual things...
Removing FetchType.EAGER
from Parent
or AnotherParent
solves the problem, but I need it, so real solution is to use @LazyCollection(LazyCollectionOption.FALSE)
instead of FetchType
(thanks to Bozho for the solution).
回答1:
I think a newer version of hibernate (supporting JPA 2.0) should handle this. But otherwise you can work it around by annotating the collection fields with:
@LazyCollection(LazyCollectionOption.FALSE)
Remember to remove the fetchType
attribute from the @*ToMany
annotation.
But note that in most cases a Set<Child>
is more appropriate than List<Child>
, so unless you really need a List
- go for Set
回答2:
Simply change from List
type to Set
type.
回答3:
Alternatively add a Hibernate-specific @Fetch annotation to your code:
@OneToMany(mappedBy=\"parent\", fetch=FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
private List<Child> childs;
This should fix the issue, related to Hibernate bug HHH-1718
回答4:
After trying with every single option describe in this posts and others, I came to the conclusion that the the fix is a follows.
In every XToMany place @XXXToMany(mappedBy=\"parent\", fetch=FetchType.EAGER)
and intermediately after
@Fetch(value = FetchMode.SUBSELECT)
This worked for me
回答5:
To fix it simply take Set
in place of List
for your nested object.
@OneToMany
Set<Your_object> objectList;
and don\'t forget to use fetch=FetchType.EAGER
it will work.
There is one more concept CollectionId
in Hibernate if you want to stick with list only.
回答6:
I found a good Blog post about the behaviour of Hibernate in this kind of object mappings: http://blog.eyallupu.com/2010/06/hibernate-exception-simultaneously.html
回答7:
you can keep booth EAGER lists in JPA and add to at least one of them the JPA annotation @OrderColumn (with obviously the name of a field to be ordered). No need of specific hibernate annotations.
But keep in mind it could create empty elements in the list if the chosen field does not have values starting from 0
[...]
@OneToMany(mappedBy=\"parent\", fetch=FetchType.EAGER)
@OrderColumn(name=\"orderIndex\")
private List<Child> children;
[...]
in Children then you should add the orderIndex field
回答8:
The reason why you get that exception is that Hibernate would end up doing a Cartesian Product which is bad for performance.
Now, although you could \"fix\" the issue by using Set
instead of List
, you shouldn\'t do that because the Cartesian Product will still be featured in the underlying SQL statements.
You are better off switching from FetchType.EAGER
to Fetchype.LAZY
since eager fetching is a terrible idea that can lead to critical application performance issues.
If you need to fetch the child entities across a multi-level hierarchy, better select from the inner-most child up to the parents, as explained in this article.
回答9:
When you have too complex objects with saveral collection could not be good idea to have all of them with EAGER fetchType, better use LAZY and when you really need to load the collections use: Hibernate.initialize(parent.child)
to fetch the data.
回答10:
We tried Set instead of List and it is a nightmare: when you add two new objects, equals() and hashCode() fail to distinguish both of them ! Because they don\'t have any id.
typical tools like Eclipse generate that kind of code from Database tables:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
You may also read this article that explains properly how messed up JPA/Hibernate is. After reading this, I think this is the last time I use any ORM in my life.
I\'ve also encounter Domain Driven Design guys that basically say ORM are a terrible thing.
回答11:
You could use a new annotation to solve this:
@XXXToXXX(targetEntity = XXXX.class, fetch = FetchType.LAZY)
In fact, fetch\'s default value is FetchType.LAZY too.