Introduction
In this article, I’m going to show you how to handle the MultipleBagFetchException thrown by Hibernate upon simultaneously fetching multiple collections with Spring Data JPA.
MultipleBagFetchException
As I explained previously in this article, the MultipleBagFetchException is thrown by Hibernate when you try to fetch multiple List collections at once.
By trying to fetch multiple one-to-many or many-to-many associations at once, a Cartesian Product is generated, and, even if Hibernate didn’t throw the MultipleBagFetchException, we would still want to avoid getting a Cartesian Product in our query result set.
Domain Model
Let’s assume we have a Post parent entity that has a bidirectional @OneToMany association with the PostComment entity and a unidirectional @ManyToMany association with the Tagentity:

The Post entity has a comments collection and a tags collection, like this:
|
|
Our goal is to fetch a number of Post entities along with their associated comments and tags collections.
Getting a MultipleBagFetchException using a Spring Data JPA Query annotation
The first approach one would take is to create a @Query method that uses JOIN FETCH on both the comments and tags collections, like in the following example:
|
|
But, if you try to do that, your Spring application will not even start, throwing the following MultipleBagFetchException upon trying to create the JPA TypedQuery from the associated @Query annotation:
|
|
How to fix the MultipleBagFetchException using a Spring Data JPA
So, while we can’t fetch both collections using a single JPA query, we can definitely use two queries to fetch all the data we need.
|
|
The findAllWithComments query will fetch the desired Post entities along with their associated PostComment entities, while the findAllWithTags query will fetch the Post entities along with their associated Tag entities.
Executing two queries will allow us to avoid the Cartesian Product in the query result set, but we’d have to aggregate the results so that we return a single collection of Post entries that contain both the comments and tags collections initialized.
And that’s where the Hibernate First-Level Cache or Persistence Context can help us achieve this goal.
The PostService defines a findAllWithCommentsAndTagsmethod that’s implemented as follows:
|
|
Since the @Transactional annotation is placed at the class level, all methods will inherit it. Therefore, the findAllWithCommentsAndTags service method is going to execute in a transactional context, meaning that both PostRepository method calls will happen in the context of the same Persistence Context.
For this reason, the findAllWithComments and findAllWithTags methods will basically return two List objects containing the very same Post object references since you can have at most one entity reference managed by a given Persistence context.
While the findAllWithComments method is going to fetch the Post entities and store them in the Persistence Context or First-Level Cache, the second method, findAllWithTags, will just merge the existing Post entities with the references fetched from the DB that now contain the tags collections initialized.
This way, both the comments and the tags collections are going to be fetched prior to returning the List of Post entities back to the service method caller.
In our integration test, we can verify that both collections have been initialized:
As you can see, we can read the size of the comments and tags collections even after the Persistence Context was closed since they’ve been fetched by the two entity query executed by the findAllWithCommentsAndTags service method.
Awesome, right?
Conclusion
Knowing how to deal with the MultipleBagFetchExceptionis very important when using Spring Data JPA, as eventually, you are going to bump into this issue.
By fetching at most one collection per query, not only that you can prevent this issue, but you will also avoid the SQL Cartesian Product that would be generated when executing a single SQL query that JOINs multiple unrelated one-to-many associations.
Reference https://vladmihalcea.com/spring-data-jpa-multiplebagfetchexception/