简体   繁体   English

查询应返回实体以及特定的相关实体

[英]query that should return entities qith specific related entities

Generally my questian is very simple I think, nevertheless I couldn't find a good solution. 通常,我认为我的询问者非常简单,但是我找不到很好的解决方案。 Let's say I have an Entity class called MyEntity which has a OneToMany relation to an Entity class called EntityAttribute , so it has a list or set attributes with objects of this class. 假设我有一个名为MyEntity的实体类,它与一个名为EntityAttribute的实体类具有OneToMany关系,因此它具有此类对象的列表或设置attributes EntityAttribute has an attribute name of type String . EntityAttribute的属性name类型为String

Now I want to implement a method which takes attribute names and returns all entities that contains for each name in attributes at least one attribute with that name. 现在,我想实现一种方法,该方法采用属性名称,并返回attributes中每个名称包含的所有实体,至少具有该名称的一个属性。 Although this sounds very straight forward, the only solution I found was to execute a query for each attribute name and merge the results like this: 尽管这听起来很简单,但是我发现的唯一解决方案是对每个属性名称执行查询并合并结果,如下所示:

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
  }

This code isn't tested but generally is one solution. 该代码未经测试,但通常是一种解决方案。 This doesn't seem to be the most efficient one. 这似乎不是最有效的一种。 Another solution I testet was to use multiple joins like 我测试的另一个解决方案是使用多个联接,例如

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

This seems to be more efficient, but it iterates over the cartesian products... So it's highly inefficient. 这似乎更有效,但是会迭代笛卡尔乘积...因此效率极低。

I could also imagine to nest subqueries, but this seems to be very complicated. 我也可以想象嵌套子查询,但这似乎很复杂。

The question simply is: What is the best solution for this problem? 问题很简单:什么是解决此问题的最佳解决方案? Afterwards I would also like to implement AND and OR, so I can query for all entities with attributes x and (y or z) or something like that. 之后,我还想实现AND和OR,因此我可以查询所有具有属性x和(y或z)或类似属性的实体。 But for now I only want to make the AND case. 但是现在我只想进行AND运算。
Thanks in advance 提前致谢

Maybe you could achieve this using in clause + group by + having + count , if I understand your question correctly. 如果我正确理解了您的问题,也许可以使用in子句+ group by + having + count来实现。 The idea is to count the number of matches for each MyEntity. 这个想法是计算每个MyEntity的匹配数。 If the count is equal to the number of attributes passed in, it means that each of them was found for that entity (assuming they are unique). 如果计数等于传入的属性数,则意味着为该实体找到了每个属性(假设它们是唯一的)。 In JPQL the query would look like this: 在JPQL中,查询如下所示:

select e from MyEntity e join e.attributes a
where a.name in (:attributeNames)
group by e having count(*) = :attributeCount

where :attributeCount is the value of attributeNames.size() . 其中:attributeCountattributeNames.size()的值。

I'm not very familiar with the criteria API, but you can experiment with something like this: 我对条件API不太熟悉,但是您可以尝试以下方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM