Hibernate:选择其中包含所有指定值的实体

时间:2012-10-08 15:39:36

标签: java hibernate collections

我需要有关棘手的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)

对此的任何帮助都将受到高度赞赏,所以非常感谢您提前。

3 个答案:

答案 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)