应该返回具有特定相关实体的实体的查询

时间:2014-10-22 18:09:52

标签: java jpa criteria-api

一般来说,我的问题非常简单,但我无法找到一个好的解决方案。假设我有一个名为MyEntity的实体类,它与名为EntityAttribute的实体类具有OneToMany关系,因此它有一个列表或集合attributes,包含此类的对象。 EntityAttribute的属性name类型为String

现在我想实现一个方法,它接受属性名称并返回包含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案件 提前致谢

1 个答案:

答案 0 :(得分:1)

如果我正确理解您的问题,也许您可​​以使用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

其中:attributeCountattributeNames.size()的值。

我对标准API不太熟悉,但你可以尝试这样的事情:

...
cq.groupBy(entity);
cq.having(cb.equal(cb.count(entity), attributeNames.size()));
// TODO: add IN clause
...