JPA : How to define @NamedEntityGraph for 3 levels?
Hibernate doesn't allow you to fetch multiple Bags because it would end up fetching a Cartesian Product.
M → N → P one-to-many or many-to-many relations
For a multi-nested hierarchy, you can use
JOIN FETCH on multiple collections as long as your lists are mapped as
M → N and M → P one-to-many or many-to-many relations
For sibling collections, like M → N and M → P, don't switch to using
Set instead of
Set instead of a
List to avoid the
MultipleBagFetchException is a very bad idea since you will still end up with a
Cartesian Product, and that's going to cause performance issues because you are going to fetch
M x N x P records.
In this case, a much better approach is to fetch one collection with the first query and use additional queries for the remaining collections:
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();
This strategy allows you to avoid the
M x N x P result set by fetching
M x (N + P) records instead.
Fetching from the child-side to the parent
If you have to use INNER JOIN when fetching the child collection, then you can simply [fetch from the inner-most Child up to the root] and reassemble the structure afterward. This is much more efficient since the query goes like this:
select t from Topic t join t.subject s join s.branch b