2012-10-08 10 views
5

Ich benötige Unterstützung bei einem schwierigen Hibernate-Abfrageproblem. Ich habe folgende Einheiten:Ruhezustand: Wählen Sie Entitäten aus, in denen die Auflistung alle angegebenen Werte enthält.

public class Book { 
    private String bookId; 
    private String author; 
    private String isbn; 
    private Set<Tag> tags; 
    // getters, setters etc. 
} 

und

public class Tag { 
    private String tagId; 
    private String tagName; 
    // getters, setters, etc. 
} 

Es gibt eine many-to-many-Verbindung zwischen den beiden, die durch eine Join-Tabelle books_tags_mn dargestellt wird, mit den Spalten book_id und tag_id.

Was ich gerne tun möchte, ist das Folgende: Ich möchte eine Ruhezustand Abfrage/Kriterien Abfrage, die alle Buch, alle eines bestimmten Satzes von Tags zurückgeben. Was funktioniert, ist die Auswahl aller Bücher, die eines Satzes von Tags haben.

Ich habe mich mit der API-Kriterien beschäftigt, aber nicht wirklich verstanden. Also, was ich versuche (in Pseudo-HQL) zu tun

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

Jede Hilfe auf diesem würde sehr geschätzt werden, so vielen Dank im Voraus.

Antwort

3

Sie könnten die folgende Abfrage verwenden:

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

wo numberOfTags die Anzahl von Tags in dem Satz von Tags, die aufeinander abgestimmt werden müssen.

+0

Dank hinzufügen, die wie ein Zauber funktioniert! –

+0

Falls die Sammlung Duplikate enthalten kann (nicht für IDs), möchten Sie vielleicht die Anzahl hinzufügen (distinct) – Ben

0

Ich würde empfehlen Ihnen zwei benutzerdefinierte Funktionen oder Einschränkung zu erstellen, wie:

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" 

Sobald Funktionen definiert und registriert werden, würden Sie in der Lage HQL/Kriterien-Abfrage auszuführen, wie:

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

oder

session.createCriteria(Book.class).add(
      Restrictions.add(collect("tags").containsAll(tags)) 
     ).list(); 

Bitte beachten Sie: Dies ist nur ein Beispiel Pseudo-Code, um die Idee zu teilen.

Hoffe, das hilft!

0

Die akzeptierte Antwort von JB Nizet ist gut, wird aber nicht funktionieren, wenn Ihre Sammlung Duplikate enthalten kann (möglicherweise ein berechtigter Grund dafür, wahrscheinlich jedoch nicht mit dem Tag-Beispiel).

Die Kollektion für einige Bücher kann doppelte Tags mit dem gleichen Namen "MyTag" enthalten. Dann kann eine Suche nach den Tags "MyTag", "YourTag" Bücher zurückgeben, die 2 "MyTag" -Tags, aber kein "YourTag" -Tag haben.

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

Wie ich sagte nichts falsch mit der Antwort akzeptiert, aber wenn Sie Duplikate in der Sammlung unterstützen müssen, dann müssen Sie count (distinct tag.name)

Verwandte Themen