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 Set.

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 List.

Using a 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][3] 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