2012-10-08 77 views
5

Necesito ayuda con un problema de consulta de hibernación complicado. Tengo las siguientes entidades:Hibernar: Seleccione las entidades donde la colección contiene todos los valus especificados

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

y

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

existe una relación de muchos a muchos entre los dos que se representa mediante una tabla de unión books_tags_mn con las columnas y book_id tag_id.

Lo que me gusta hacer es la siguiente: Quiero crear una consulta/criterios de hibernación consulta que devuelve todo libro que tiene todas de un determinado conjunto de etiquetas. Lo que sí funciona es seleccionar todos los libros que tengan cualquier de un conjunto de etiquetas.

He estado jugando con la API de criterios, pero realmente no lo entiendo. Así que lo que estoy tratando de hacer (en seudo HQL)

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

Cualquier ayuda en esto sería muy apreciada, así que muchas gracias de antemano.

Respuesta

3

podría utilizar la siguiente consulta:

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

donde numberOfTags es el número de etiquetas en el conjunto de etiquetas que debe ser igualada.

+0

Gracias que funciona como un encanto! –

+0

En caso de que la colección pueda contener duplicados (no en ID), es posible que desee agregar recuento (distinto) – Ben

0

Yo aconsejaría a crear dos funciones o restricción en cuanto personalizados:

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" 

Una vez funciones están definidas y registradas, que sería capaz de ejecutar HQL/criterios de consulta como:

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

o

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

Nota: Este es solo un pseudo código de muestra para compartir la idea.

Espero que esto ayude!

0

La respuesta aceptada de JB Nizet es buena, pero no funcionará si su colección puede contener duplicados (podría ser una razón válida para eso, aunque probablemente no con el ejemplo de la etiqueta).

Digamos que la colección de algunos libros puede contener etiquetas duplicadas con el mismo nombre "MyTag". Luego, una búsqueda de las etiquetas "MyTag", "YourTag" podría devolver libros que tienen 2 etiquetas "MyTag" pero ninguna etiqueta "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)) 

Como ya he dicho nada malo con la respuesta aceptada, pero si es necesario apoyar los duplicados en la colección, entonces necesito agregar recuento (distinta tag.name)

Cuestiones relacionadas