Hibernate Exception - Simultaneously Fetch Multiple Bags

Hibernate Exception - Simultaneously Fetch Multiple Bags

One of my customers has just upgraded to JBoss 4.0.4-GA, the process also required us to upgrade Hibernate products to the following versions:
  • Hibernate core – 3.2.0CR2
  • Hibernate Entity Manager – 3.2.0CR1
  • Hibernate annotations- 3.2.0CR1
We fixed some minor changes and improvements and then we bumped into the following exception 

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 

   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 
   PARENT parent0_ left outer join 
           CHILD1 child1s1_ on parent0_.id=child1s1_.parent_id left outer join 
           CHILD2 child2s2_ on parent0_.id=child2s2_.parent_id 


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)
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

Solving the Simultaneously Fetch Multiple Bags Exception using idbags


Anonymous said…
Hi, all is going perfectly here and ofcourse
every one is sharing information, that's really fine, keep up writing.

Also visit my webpage; ranking kredytów hipotecznych

Popular posts from this blog

PostgreSQL bytea and oid

MySQL as Hive metadata store

Big Memory Go.