简体   繁体   English

严格的条款内的Spring数据

[英]Spring Data with strict In-clause

See updated question below 请参阅下面的更新的问题

I want to query for elements where every element is required to have all given attributes of eg a set to be returned, not only one. 我想查询元素,其中每个元素都必须具有所有给定的属性,例如要返回的一组属性,而不仅仅是一个。

Default Spring Data Jpa Query, where one attribute is enough: 默认的Spring Data Jpa查询,其中一个属性就足够了:

findAllByAttributeIn(Set<Attribute> setAttr)

Example problem 示例问题

For these elements (abstracted, no actual table) 对于这些元素(抽象,无实际表)

id | attr
----------
1  | A
2  | A,B
3  | A,B,C

with this filter: 使用此过滤器:

setAttr: [A,B] setAttr:[A,B]

the default query 默认查询

findAllByAttributeIn(Set<Attribute> setAttr)

returns all elements (by ids): 返回所有元素(按ID):

[1,2,3] [1,2,3]

Desired result is only the second element (with [A,B]). 所需的结果只是第二个元素(带有[A,B])。

Is that possible with the given Spring Data Jpa query keywords or is the only solution to create a custom query? 使用给定的Spring Data Jpa查询关键字是否有可能,还是创建自定义查询的唯一解决方案?

Updated question: 更新的问题:

There are two entities, Media and Tag. 有两个实体,媒体和标签。 They have a many-to-many relationship which is realised in the table Media_has_tags. 它们具有多对多关系,该关系在表Media_has_tags中实现。 Every media can have any number of tags (0..*). 每个媒体可以具有任意数量的标签(0 .. *)。 So in my Spring app, media has a set of tags as an attribute and vice versa. 因此,在我的Spring应用程序中,媒体具有一组标签作为属性,反之亦然。 The classes: 这些课程:

Media = {
id: string,
Set<Tag> tags,
...
}

Tag = {
id: string,
Set<Media> medias,
...
}

The corresponding tables are: 相应的表是:

Media
-------
id | ...

Tag
-------
id    | ...
title | ...

Media_has_tags
-------
media_id | tag_id

And now I have a set of tags with which I want to get all medias which have every tag of that set. 现在,我有了一组标签,我想用它们来获取所有包含该标签的每个标签的媒体。 They can have more tags of course, but they need to have every tag of the set I am providing. 他们当然可以具有更多标签,但是他们需要具有我提供的集合中的每个标签。

Concrete example: 具体示例:

Media
-------
id | ...
-------
1  |
2  |

Tag
-------
id | title | ...
1  | A     |
2  | B     |

Media_has_tags
-------
media_id | tag_id
1        | 1
2        | 1
2        | 2

Given a set of tags [A, B] I want only media with id 2 as a result since media with id 1 doesn't have tag 'B'. 给定一组标签[A,B],我只想要ID为2的媒体,因为ID为1的媒体没有标签'B'。

Can I achieve that with Keywords and if, how or do I have to build my own query? 我可以使用关键字来实现吗?是否,如何或必须建立自己的查询?

Sorry, but your question is incorrect initially. 抱歉,您的问题最初是不正确的。

findAllByAttributeIn(Set<Attribute> setAttr)

produces an SQL request like this: 产生这样的SQL请求:

select * from <table_name> t where t.attribute in (?,?,?...?)

So according to RDBMS-rules your result is correct and expectable. 因此,根据RDBMS规则,您的结果是正确且可预期的。 What is a real structure for your abstract tables? 您的抽象表的实际结构是什么?

 id | attr
----------
 1  | A
 2  | A,B
 3  | A,B,C

In real life it would be somethink like this: 在现实生活中,可能是这样的:

 id | attr
----------
 1  | A
 2  | A
 2  | B
 3  | A
 3  | B
 3  | C

And again - in this case the result you have got is ok for any RDBMS. 再一次-在这种情况下,对于任何RDBMS来说,您得到的结果都是可以的。 Give us real examples from your project, please 请给我们您项目的真实例子

Update because of question update : 由于问题更新而更新

OK, the problem has been clarified. 好的,问题已经解决。 In this case there is no straight way to solve it using standard CrudRepository syntax. 在这种情况下,没有使用标准CrudRepository语法解决它的直接方法。 But you can try to write @Query request to manage to get the goal. 但是您可以尝试编写@Query请求以设法达到目标。 In a clear SQL this problem has to be solved by using group by together with having . 在清晰的SQL中,必须通过使用group byhaving来解决此问题。 It would be something like this: 就像这样:

select media_id 
From media_has_tags
Where tag_id in(1,2 3)
Group by media_id
Having count(*)=3

In terms of SpringData it means that you have to create MediaHasTagsRepository interface and an appropriate query method to get looked ids. MediaHasTagsRepository而言,这意味着您必须创建MediaHasTagsRepository接口和适当的查询方法来获取MediaHasTagsRepository ID。 After that you can easily find medias you're looking for. 之后,您可以轻松找到所需的媒体。 But this approach is not looking good IMHO. 但是这种方法看起来不好恕我直言。 The best way I suppose is to find all the medias by the your initial query and than filter them by the given condition in Java. 我想最好的方法是通过您的初始查询找到所有媒体,然后按照Java中的给定条件过滤它们。 Eg you have a List<Media> where each element has an least a one tag that you are looking for. 例如,您有一个List<Media> ,其中每个元素至少都有一个您要查找的标签。 Then we can do a loop to find medias that contains all the looked tags: 然后,我们可以循环查找包含所有已查看标签的媒体:

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.

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