Hibernate throws MultipleBagFetchException - cannot simultaneously fetch multiple bags
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
But remind that with using sets you won't eliminate the underlaying Cartesian Product as described by Vlad Mihalcea in his answer!
org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
Hibernate doesn't allow fetching more than one bag because that would generate a Cartesian product.
Now, you will find lots of answers, blog posts, videos, or other resources telling you to use a Set
instead of a List
for your collections.
That's terrible advice!
Using Sets
instead of Lists
will make the MultipleBagFetchException
go away, but the Cartesian Product will still be there.
The right fix
Instead of using multiple JOIN FETCH
in a single JPQL or Criteria API query:
List<Post> posts = entityManager.createQuery("""
select p
from Post p
left join fetch p.comments
left join fetch p.tags
where p.id between :minId and :maxId
""", Post.class)
.setParameter("minId", 1L)
.setParameter("maxId", 50L)
.getResultList();
You can do the following trick:
List<Post> posts = entityManager.createQuery("""
select distinct p
from Post p
left join fetch p.comments
where p.id between :minId and :maxId
""", Post.class)
.setParameter("minId", 1L)
.setParameter("maxId", 50L)
.setHint(QueryHints.PASS_DISTINCT_THROUGH, false)
.getResultList();
posts = entityManager.createQuery("""
select distinct p
from Post p
left join fetch p.tags t
where p in :posts
""", Post.class)
.setParameter("posts", posts)
.setHint(QueryHints.PASS_DISTINCT_THROUGH, false)
.getResultList();
As long as you fetch at most one collection using JOIN FETCH
, you will be fine. By using multiple queries, you will avoid the Cartesian Product since any other collection but the first one is fetched using a secondary query.
Hibernate : org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
As the exception says to you, you can't fetch two related collections or bags simultaneously. A quick solution would be to remove the FetchType.EAGER
from one collection and force the fetching of that collection explicitly calling the collection objects.
For example, if you remove the FetchType.EAGER
from shippingAddress
collection, you can force the fetching like this:
public List<Order> getOrderByCustomerId(Customer customer) {
Criteria criteria = session.createCriteria(Order.class);
List<Order> res = (List<Order>) criteria.add(Restrictions.eq("customer",customer)).list();
for (Order order : res)
order.getCustomer().getShippingAddress().size();
return res;
}
Calling the size()
method of the collection will force the fetching of all the elements of that collection.
More information about this topic:
Hibernate cannot simultaneously fetch multiple bags
MultipleBagFetchException: cannot simultaneously fetch multiple bags
The regular fix for solving MultipleBagFetchException
is change List
typed fields on Set
typed, like this:
...
public class RegisteredProgram extends Auditable<String> {
@OneToMany(mappedBy = "registeredProgram", cascade = CascadeType.ALL)
@JsonBackReference
private Set<Trainer> trainerList = new HashSet<>();
@OneToMany(mappedBy = "registeredProgram", cascade = CascadeType.ALL)
@JsonBackReference
private Set<Official> officialList = new HashSet<>();
...
}
For more details see: https://thorben-janssen.com/hibernate-tips-how-to-avoid-hibernates-multiplebagfetchexception/
Note: Remember about equals
and hashcode
for Set
data structure and avoiding Lombok & Hibernate pitfalls(https://thorben-janssen.com/lombok-hibernate-how-to-avoid-common-pitfalls/). Please pay attention for 'Avoid @Data' topic, because I see you are using that combination, that combination can produce unexpected behavior!
Hibernate 4.3 to 5.2 upgrade - cannot simultaneously fetch multiple bags
This issue has been resolved now.
In a couple of my entities I was using a List
for @OneToMany
.
Changing to Set
resulted in the error going away. Not sure as yet why this worked/was supported in Hibernate 4.3.11 and not 5.2.9. I will update this answer if I find any further information.
Further info with regard to List
vs Set
can be found here and here.
Related Topics
How to Force Garbage Collection in Java
Y Returns 2012 While Y Returns 2011 in Simpledateformat
Overriding the Java Equals() Method - Not Working
How to Parse/Format Dates With Localdatetime - Java 8
How to List the Files Inside a Jar File
How Many Ways to Click on Webelement in Webdriver
Ways to Iterate Over a List in Java
Why Does the Foreach Statement Not Change the Element Value
Sorting an Arraylist of Objects Using a Custom Sorting Order
How to Get X and Y Index of Element Inside Gridlayout
What Are the Effects of Exceptions on Performance in Java
How to Run Unix Shell Script from Java Code
What Does Servletcontext.Getrealpath("/") Mean and When Should I Use It
How to Format a Number in Java
What's the Difference Between ".Equals" and "=="
How to Run Test Methods in Specific Order in Junit4
Program Not Accessing Method Paintcomponent() of Extended Jpanel Class