![](/img/trans.png)
[英]Spring Data JPA repositories: IN-clause in derived query not working
[英]Spring Data with strict In-clause
我想查询元素,其中每个元素都必须具有所有给定的属性,例如要返回的一组属性,而不仅仅是一个。
默认的Spring Data Jpa查询,其中一个属性就足够了:
findAllByAttributeIn(Set<Attribute> setAttr)
示例问题
对于这些元素(抽象,无实际表)
id | attr
----------
1 | A
2 | A,B
3 | A,B,C
使用此过滤器:
setAttr:[A,B]
默认查询
findAllByAttributeIn(Set<Attribute> setAttr)
返回所有元素(按ID):
[1,2,3]
所需的结果只是第二个元素(带有[A,B])。
使用给定的Spring Data Jpa查询关键字是否有可能,还是创建自定义查询的唯一解决方案?
有两个实体,媒体和标签。 它们具有多对多关系,该关系在表Media_has_tags中实现。 每个媒体可以具有任意数量的标签(0 .. *)。 因此,在我的Spring应用程序中,媒体具有一组标签作为属性,反之亦然。 这些课程:
Media = {
id: string,
Set<Tag> tags,
...
}
Tag = {
id: string,
Set<Media> medias,
...
}
相应的表是:
Media
-------
id | ...
Tag
-------
id | ...
title | ...
Media_has_tags
-------
media_id | tag_id
现在,我有了一组标签,我想用它们来获取所有包含该标签的每个标签的媒体。 他们当然可以具有更多标签,但是他们需要具有我提供的集合中的每个标签。
具体示例:
Media
-------
id | ...
-------
1 |
2 |
Tag
-------
id | title | ...
1 | A |
2 | B |
Media_has_tags
-------
media_id | tag_id
1 | 1
2 | 1
2 | 2
给定一组标签[A,B],我只想要ID为2的媒体,因为ID为1的媒体没有标签'B'。
我可以使用关键字来实现吗?是否,如何或必须建立自己的查询?
抱歉,您的问题最初是不正确的。
findAllByAttributeIn(Set<Attribute> setAttr)
产生这样的SQL请求:
select * from <table_name> t where t.attribute in (?,?,?...?)
因此,根据RDBMS规则,您的结果是正确且可预期的。 您的抽象表的实际结构是什么?
id | attr
----------
1 | A
2 | A,B
3 | A,B,C
在现实生活中,可能是这样的:
id | attr
----------
1 | A
2 | A
2 | B
3 | A
3 | B
3 | C
再一次-在这种情况下,对于任何RDBMS来说,您得到的结果都是可以的。 请给我们您项目的真实例子
由于问题更新而更新 :
好的,问题已经解决。 在这种情况下,没有使用标准CrudRepository语法解决它的直接方法。 但是您可以尝试编写@Query
请求以设法达到目标。 在清晰的SQL中,必须通过使用group by
和having
来解决此问题。 就像这样:
select media_id
From media_has_tags
Where tag_id in(1,2 3)
Group by media_id
Having count(*)=3
就MediaHasTagsRepository
而言,这意味着您必须创建MediaHasTagsRepository
接口和适当的查询方法来获取MediaHasTagsRepository
ID。 之后,您可以轻松找到所需的媒体。 但是这种方法看起来不好恕我直言。 我想最好的方法是通过您的初始查询找到所有媒体,然后按照Java中的给定条件过滤它们。 例如,您有一个List<Media>
,其中每个元素至少都有一个您要查找的标签。 然后,我们可以循环查找包含所有已查看标签的媒体:
List<Media> list; // here is a filled list of medias
Set<String> titles; // here is a set of title interseptions we a looking for
final List<Media> result = new ArrayList<>();
for (Media media: list) {
if (!list.getTags().isEmpty()){
Set<String> tagTitles = list.getTags().stream().map(item -> item.getTitle()).filter(title -> titles.contains(title)).distinct().collect(Collectors.toSet());
if (tagTitles.size() == titles.size()) {
result.add(media);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.