总的来说,我认为我的问题很简单,但我找不到好的解决方案。假设我有一个名为 MyEntity
的实体类,它与名为 EntityAttribute
的实体类具有 OneToMany 关系,因此它具有包含此类对象的列表或设置 attributes
。 EntityAttribute
具有 String
类型的属性 name
。
现在我想实现一种方法,该方法采用属性名称并返回对于 attributes
中的每个名称至少包含一个具有该名称的属性的所有实体。虽然这听起来非常简单,但我发现的唯一解决方案是对每个属性名称执行查询并合并结果,如下所示:
for (String name : attributeNames) {
CriteriaQuery<MyEntity> cq = cb.createQuery(MyEntity.class);
Root<MyEntity> entity = cq.from(MyEntity.class);
Join<MyEntity, EntityAttribute> attributeJoin = entity.join(MyEntity_.attributes);
cq.where(attributeJoin.get(EntityAttribute_.name).equals(name));
cq.select(entity);
... // get result list and merge
}
此代码未经测试,但通常是一种解决方案。这似乎不是最有效的一种。 我测试的另一个解决方案是使用多个连接,例如
CriteriaQuery<MyEntity> cq = cb.createQuery(MyEntity.class);
Root<MyEntity> entity = cq.from(MyEntity.class);
List<Predicate> predicates = new ArrayList<>();
for (String name : attributeNames) {
Join<MyEntity, EntityAttribute> attributeJoin = entity.join(MyEntity_.attributes);
predicates.add(attributeJoin.get(EntityAttribute_.name).equals(name));
}
cq.select(predicates.toArray(new Predicate[] {}));
... // get result list
这似乎更有效,但它迭代笛卡尔积......所以效率非常低。
我也可以想象嵌套子查询,但这似乎很复杂。
问题很简单:这个问题的最佳解决方案是什么?之后我还想实现 AND 和 OR,这样我就可以查询具有属性 x 和(y 或 z)或类似属性的所有实体。但现在我只想做 AND 案例。
提前致谢
最佳答案
如果我正确理解你的问题,也许你可以使用in
子句+group by
+having
+count
来实现这一点。这个想法是计算每个 MyEntity 的匹配数。如果计数等于传入的属性数量,则意味着为该实体找到了每个属性(假设它们是唯一的)。在 JPQL 中,查询将如下所示:
select e from MyEntity e join e.attributes a
where a.name in (:attributeNames)
group by e having count(*) = :attributeCount
其中 :attributeCount
是 attributeNames.size()
的值。
我对标准 API 不太熟悉,但你可以尝试一下这样的东西:
...
cq.groupBy(entity);
cq.having(cb.equal(cb.count(entity), attributeNames.size()));
// TODO: add IN clause
...
关于java - 应返回具有特定相关实体的实体的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26514219/