Hibernate Exception - Simultaneously Fetch Multiple Bags
Hibernate Exception - Simultaneously Fetch Multiple Bags
- Hibernate core – 3.2.0CR2
- Hibernate Entity Manager – 3.2.0CR1
- Hibernate annotations- 3.2.0CR1
javax.persistence.PersistenceException: org.hibernate.HibernateException: cannot simultaneously fetch multiple bags
at org.hibernate.ejb.Ejb3Configuration.createEntityManagerFactory(Ejb3Configuration.java:217)
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:114)
So what is the problem?
When an entity has more than one non-lazy association that might be interpreted as a bag (e.g., java.util.List or java.util.Collection properties annotated with @org.hibernate.annotations.CollectionOfElements or @OneToMany or @ManyToMany and not annotated with @org.hibernate.annotations.IndexColumn) hibernate will fail to fetch the entity correctly.Lets say that we have a Parent class, and two children classes (Child1 and Child2), the parent class has a bag for each of the children types, as illustrated by the following mapping
@OneToMany(mappedBy="parent",cascade=CascadeType.ALL, fetch=FetchType.EAGER)
List child1s = new LinkedList();
@OneToMany(mappedBy="parent",cascade=CascadeType.ALL, fetch=FetchType.EAGER)
List child2s= new LinkedList();
We have to notice the bag semantic and the EAGER fetching on both associations, the cascading is not important to our problem. When parsing the mapping Hibernate pre-build the following (I changed the columns aliases for readability) SQL select
parent0_.id as p_id, parent0_.name as p_name, child1s1_.parent_id as c1_p_id,
child1s1_.id as c1_id, child1s1_.id as c1_id_1, child1s1_.parent_id as
c1_p_id_1, child1s1_.value as c1_val,child2s2_.parent_id as c2_p_id,
child2s2_.id as c2_id, child2s2_.id as c2_id_,
child2s2_.parent_id as c2_p_id_1, child2s2_.value as c2_val
from
PARENT parent0_ left outer join
CHILD1 child1s1_ on parent0_.id=child1s1_.parent_id left outer join
CHILD2 child2s2_ on parent0_.id=child2s2_.parent_id
where
parent0_.id=?
Workarounds
I've found three strategies to overcome this issue, the first one is to use LAZY fetching when possible. I don't even have to change all of my associations to be lazy fetched, I just can't have more than one EGAR association on the same entity. The second solution is to replace bag semantics with List semantics this can be done by adding the @IndexColumn on the relation.
@OneToMany(mappedBy="parent",cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@IndexColumn(name="INDEX_COL")
List child1s = new LinkedList();
The usage of @IndexColumn helps solving the problem since now Hibernate has a List semantic for the association and when fetching the parent it also fetches the index of each element on the list. Using this index Hibernate can tell if the element on the list has already been loaded. We have to remember that by adding @IndexColumn on the inverse side of an association (as illustrated above) we have to maintain the index “by hand”, Hibernate doesn't maintain the index on the inverse side of the relation (I'll explain how we can instruct Hibernate to maintain such an index on one of the next entries in this blog).The third solution is to replace java.util.List and java.util.Collection with java.util.Set. We have to think about it - do we really need a List/Collection (a bag)? In many cases the only reason to use a List is that we are used to.
More Info (reference) : http://jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetch_multiple
http://jroller.com/eyallupu/entry/solving_the_simultaneously_fetch_multiple1
Solving the Simultaneously Fetch Multiple Bags Exception using idbags
Comments
every one is sharing information, that's really fine, keep up writing.
Also visit my webpage; ranking kredytów hipotecznych