我有一个像这样的对象模型:
class EntityA
{
...
IList<EntityB> BList;
...
}
class EntityB
{
...
IList<EntityC> CList;
}
我必须获取所有的colelctions(EntityA中的Blist和EntityB中的CList),因为如果他们都需要进行一些操作,如果我不急于加载它们,我将有选择n + 1问题。 所以查询是这样的:
select a from EntityA a left join fetch a.BList b left join fetch b.CList c
我遇到这个问题的第一个问题是从数据库返回重复项,我有EntityA重复项,因为左边的连接提取与BList。 快速阅读hibernate文档,并有一些解决方案,首先我尝试了distinct关键字,supposelly不会复制SQL distinct关键字,除了在某些情况下,也许这是其中一个案例因为我有一个SQL错误说我无法选择distict text列(EntityA表中的[Observations]列)。所以我使用了其他解决方案之一:
query.SetResultTransformer(new DistinctRootEntityResultTransformer());
这很好用。但是操作的结果仍未通过测试。我进一步检查了一下,我发现现在有重复的EntityB,因为左边的连接提取与CList。
问题是,我如何在二级集合中使用distinct?我搜索过,我只找到根实体的直接子集合的解决方案,但从来没有为二级子集合找到...
感谢您的时间
答案 0 :(得分:0)
你无法以简单的方式完成你想要的任务。我相信这是导致重复的C的左连接提取。生成的查询是这样的:
select a
left join a.b b
left join b.c c
并且db返回的行将如下所示:
1: a1 | b1 | c1
2: a1 | b1 | c2
3: a1 | b2 | c3
4: a1 | b2 | c4
...
你已经过滤了根实体重复项( A ),由于C上的外部联接,数据库需要返回 B 每个 C 条目的表格。
解决此问题的一种简单方法是通过实用程序集合过滤项目。根据您的实体要求,您还可以使用HashSet
,以便自动过滤掉它们。
答案 1 :(得分:0)
使用ISet
代替IList
(并将其映射为套装,而不是袋子)。
Set不允许重复的实体。
答案 2 :(得分:0)
我遇到了同样的问题,无法通过hql解决重复问题。但是,我为所有集合创建了IEqualityComparer,并在每个Collection上执行Disinct()以消除hql结果之上的重复。