6

我需要帮助解决棘手的休眠查询问题。我有以下实体:

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.
}

两者之间存在多对多关联,由带有 book_id 和 tag_id 列的连接表 books_tags_mn 表示。

我喜欢做以下事情:我想创建一个休眠查询/条件查询,它返回所有具有所有特定标签集的书。起作用的是选择具有任何一组标签的所有书籍。

我一直在搞乱标准 API,但并没有真正理解它。所以我想做的是(在伪 HQL 中)

from Book book where book.tags containsAll(:tags)

对此的任何帮助将不胜感激,因此在此先感谢您。

4

3 回答 3

6

您可以使用以下查询:

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是一组标签中必须匹配的标签数量。

于 2012-10-08T18:02:23.830 回答
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)

于 2014-12-19T15:27:29.727 回答
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();

请注意:这只是一个示例伪代码来分享这个想法。

希望这可以帮助!

于 2012-10-08T16:16:13.967 回答