JPA : How to define @NamedEntityGraph for 3 levels?

匿名 (未验证) 提交于 2019-12-03 08:36:05

问题:

I have 3 entities. Branch,Subject,Topic. Branch has list of subjects and Subject has list of topics. Also subjectList and topicList both are lazy. I want to fetch all branch including its subjects and topics in single query.

1.

@Entity public class Branch implements Serializable  {     private static final long serialVersionUID = 1L;     @Id     @GeneratedValue(strategy = GenerationType.AUTO)     private Integer id;     private String name;      @OneToMany(mappedBy = "branch")     private List<Subject> subjectList;     //Getters and Setters } 

2.

@Entity public class Subject implements Serializable  {     private static final long serialVersionUID = 1L;     @Id     @GeneratedValue(strategy = GenerationType.AUTO)     private Integer id;      private String name;      @ManyToOne()     private Branch branch;      @OneToMany(mappedBy = "subject")     private List<Topic> topicList;     //Getters and Setters        } 

3.

@Entity public class Topic implements Serializable  {     private static final long serialVersionUID = 1L;     @Id     @GeneratedValue(strategy = GenerationType.AUTO)     private Integer id;     private String name;      @ManyToOne()     private Subject subject;     //Getters and Setters } 

I have tried below method but it not working.

@NamedEntityGraph(name="branch_subject",  attributeNodes = {     @NamedAttributeNode(value="name"),     @NamedAttributeNode(value="subjectList", subgraph = "subjectListGraph") }, subgraphs = {     @NamedSubgraph(name="subjectListGraph",             attributeNodes = {                 @NamedAttributeNode(value="name"),                 @NamedAttributeNode(value = "topicList", subgraph = "topicListGraph")             }     ),     @NamedSubgraph(name="topicListGraph",             attributeNodes = {                     @NamedAttributeNode("name")             }     ) } ) 

Also following code is used to fetch data from database, I am using JPQL as follows

    EntityGraph branchEntityGraph = entityManager                 .getEntityGraph("branch_subject");          Branch branch = entityManager                 .createQuery("SELECT b from Branch b WHERE b.id=:ID",                         Branch.class)                 .setHint("javax.persistence.loadgraph", branchEntityGraph)                 .setParameter("ID", branch1.getId()).getResultList().get(0); 

This gives below exception

org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags 

回答1:

Hibernate doesn't allow you to fetch multiple Bags because it would end up fetching a Cartesian Product.

  1. You either make your collection Sets, instead of Lists and face the Cartesian Product performance issues.

  2. If you already INNER JOIN relations, you could 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 

    The EntityGraphBuilder, I described in my article is very easy to be adapted to your use case.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!