一般来说,我的问题非常简单,但我无法找到一个好的解决方案。假设我有一个名为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案件 提前致谢
答案 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
其中:attributeCount
是attributeNames.size()
的值。
我对标准API不太熟悉,但你可以尝试这样的事情:
...
cq.groupBy(entity);
cq.having(cb.equal(cb.count(entity), attributeNames.size()));
// TODO: add IN clause
...