我需要有关棘手的hibernate查询问题的帮助。我有以下实体:
public class Book {
private String bookId;
private String author;
private String isbn;
private Set<Tag> tags;
// getters, setters etc.
}
和
public class Tag {
private String tagId;
private String tagName;
// getters, setters, etc.
}
两者之间存在多对多关联,由连接表books_tags_mn以及book_id和tag_id列表示。
我喜欢做的是:我想创建一个hibernate查询/条件查询,它返回所有具有某组标签全部的图书。选择所有具有任何一组标签的书籍是可行的。
我一直在搞乱API标准,但并没有真正理解它。那么我正在尝试做什么(在伪HQL中)
from Book book where book.tags containsAll(:tags)
对此的任何帮助都将受到高度赞赏,所以非常感谢您提前。
答案 0 :(得分:5)
您可以使用以下查询:
select book from Book book
where :numberOfTags = (select count(tag.id) from Book book2
inner join book2.tags tag
where book2.id = book.id
and tag in (:tags))
其中numberOfTags
是必须匹配的标记集中的标记数。
答案 1 :(得分:0)
我建议您创建两个自定义函数或限制:
collect(book.tags) -> returns list of tags associated with the book
containsAll(bookTagsList, tags) --> validates and returns true if all
tags elements are present in bookTagsList
returned by the first function "collect"
定义和注册函数后,您就可以运行HQL /条件查询,如:
from Book book where containsAll(collect(book.tags), :tags)
或
session.createCriteria(Book.class).add(
Restrictions.add(collect("tags").containsAll(tags))
).list();
请注意:这只是一个分享想法的示例伪代码。
希望这有帮助!
答案 2 :(得分:0)
JB Nizet接受的答案是好的,但是如果你的集合可以包含重复项,那么它将不起作用(可能是一个有效的原因,但可能没有标签示例)。
让我们说一些书籍的集合可以包含具有相同名称“MyTag”的重复标签。然后搜索标签“MyTag”,“YourTag”可以返回具有2个“MyTag”标签但没有“YourTag”标签的书籍。
select b from Book b where :numberOfTags = (select count(distinct tag.tagName) from Book b2 inner join b2.tags tag where b2.id = b.id and tag.tagName IN (:tagNames))
正如我说接受的答案没有错,但如果你需要支持集合中的重复项,那么你需要添加count(distinct tag.name)