我们正在尝试实现一个简单的分层数据模型,如下所示。
public class Team {
/* ... */
@OneToMany(fetch = FetchType.LAZY, mappedBy = "team")
protected List<Member> members;
}
public class Member {
/* ... */
@ManyToOne(fetch = FetchType.LAZY)
protected Team team;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "member")
protected List<Assignment> assignments;
}
public class Assigment {
/* ... */
@ManyToOne(fetch = FetchType.LAZY)
protected Member member;
}
映射背后的想法非常简单 - 团队由成员组成,而成员又被分配了一些职责。
问题:创建一个查询,该查询将返回team-&gt; member-&gt;分配的层次结构,其中包含对分配施加的条件(例如,<1周内的截止日期)。
到目前为止的解决方案:
以下查询:
SELECT t FROM Team t
left join fetch t.members m
left join fetch m.assignments
不幸的是,即使没有任何条件进行分配过滤,查询也会失败,抛出:
org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
我不明白为什么它不允许同时抓取两个关系,因为Hibernate docs中显示了一个类似的例子:
from Cat as cat
inner join fetch cat.mate
left join fetch cat.kittens child
left join fetch child.kittens
问题:
其他信息:我们正在使用Hibernate 4.3.5.FINAL&amp;的PostgreSQL。
答案 0 :(得分:0)
双重抓取意味着笛卡尔积,所以如果你有100个团队,100个成员和100个作业,你将获得100 x 100 X 100 = 1,000,000个结果。
获取的最佳方式是自下而上。
SELECT a FROM Assigment a
inner join fetch a.member m
inner join fetch m.team t
从下到上重建树。您可以使用this article中解释的EntityGraphBuilder。
答案 1 :(得分:0)
是否可以通过过滤获取整个树状集合 使用单个SQL语句的叶级(赋值)?如果没有,那是什么 在拟议的解决方案中可以改进吗?
是的,这是可能的。但是,您需要更改映射以使用Set
而不是List
。
为什么双重提取无法正常工作?
当您尝试获取多个集合时,同一查询中不能有两个或更多List
。
因此,将作业或成员从List
更改为Set
。
要过滤您cannot do that in a fetched clause的分配。如果要获取所有集合并在分配中执行过滤,则查询可以是:
SELECT t FROM Team t
join fetch t.members m -- only for fetch
join fetch m.assignments -- only for fetch
join t.members member -- new join to do the where
join member.assigments assigment -- new join to do the where
where assigment.anyAttribute = someValue -- filter assigment
但是,正如@Vlad所说,使用这种解决方案的笛卡尔积很大,并且在SQL结果中带来了大量不必要的信息。