6

トリッキーな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.
}

2つの間には、book_id列とtag_id列を持つ結合テーブルbooks_tags_mnで表される多対多の関連付けがあります。

私がやりたいのは次のとおりです。特定のタグセットをすべて含むすべての本を返すHibernateクエリ/基準クエリを作成したいと思います。動作するのは、タグのセットのいずれかを持つすべての本を選択することです。

私は基準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

次のように2つのカスタム関数または制限を作成することをお勧めします。

 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 に答える
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 に答える