![](/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.