JPA:如何定义3个级别的@NamedEntityGraph?

时间:2015-05-27 10:25:30

标签: java hibernate jpa orm jpql

我有3个实体。分公司,主题,话题。 分支具有主题列表,主题具有主题列表。也 subjectList和topicList都是懒惰的。我想要获取所有分支 包括单个查询中的主题和主题。

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
}

我尝试了下面的方法,但它没有用。

@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")
            }
    )
}
)

以下代码也用于从中获取数据 数据库,我使用JPQL如下

    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);

这给出了以下异常

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

2 个答案:

答案 0 :(得分:8)

Hibernate不允许您获取多个行李,因为它最终会获取笛卡尔积。

  1. make your collection Sets, instead of Lists并面临笛卡尔产品性能问题。

  2. 如果您已经有INNER JOIN关系,那么您可以简单地fetch from the inner-most Child up to the root然后重新组合该结构。由于查询如下所示,因此效率更高:

    select t 
    from Topic t
    join t.subject s
    join s.branch b
    

    我在文章中描述的EntityGraphBuilder很容易适应您的使用案例。

答案 1 :(得分:0)

我想我也有类似的问题。我所有的Device实体都有一个Transaction对象,在我的情况下,该对象存储datetime以及该特定对象的用户和计算机信息。还有一个DeviceType实体,该实体具有事务对象,并且与我的Device实体具有多对一关系。因此,实际上,我与此Transaction Entity有1级和2级嵌套关系。因此,我有一些嵌套异常。使用Subgraph为我解决了这个问题。这是我的NamedEntityGraphs定义代码。希望对您有所帮助:

@NamedEntityGraphs(value = {
    @NamedEntityGraph(name = "Device.AllRelations",
            attributeNodes = {
                    @NamedAttributeNode("transaction"),
                    @NamedAttributeNode(value = "deviceType", subgraph = "DeviceType.Transaction")
            },
            subgraphs = {
                    @NamedSubgraph(name = "DeviceType.Transaction", attributeNodes = {
                            @NamedAttributeNode("transaction")
                    })
            }
    ),

    @NamedEntityGraph(name = "Device.TransactionOnly", attributeNodes = {
            @NamedAttributeNode("transaction")
    }),
})