Hibernate Throws Multiplebagfetchexception - Cannot Simultaneously Fetch Multiple Bags

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



Leave a reply



Submit