Cláusula JPQL IN: Java-Arrays (o Listas, Conjuntos…)?

108

Me gustaría cargar todos los objetos que tienen una etiqueta textual establecida en cualquiera de un número pequeño pero arbitrario de valores de nuestra base de datos. La forma lógica de hacer esto en SQL sería construir una cláusula "IN". JPQL permite IN, pero parece que me obliga a especificar todos los parámetros en IN directamente (como en, "in (: in1,: in2,: in3)").

¿Hay alguna forma de especificar una matriz o una lista (o algún otro contenedor) que debería desenrollarse a los valores de una cláusula IN?

Bernd Haug
fuente

Respuestas:

208

No estoy seguro de JPA 1.0, pero puede pasar un Collectionen JPA 2.0:

String qlString = "select item from Item item where item.name IN :names"; 
Query q = em.createQuery(qlString, Item.class);

List<String> names = Arrays.asList("foo", "bar");

q.setParameter("names", names);
List<Item> actual = q.getResultList();

assertNotNull(actual);
assertEquals(2, actual.size());

Probado con EclipseLInk. Con Hibernate 3.5.1, deberá rodear el parámetro entre paréntesis:

String qlString = "select item from Item item where item.name IN (:names)";

Pero esto es un error, la consulta JPQL en el ejemplo anterior es JPQL válido. Consulte HHH-5126 .

Pascal Thivent
fuente
5
¿Hay un número máximo de nombres para usar en "cláusula in"?
Gondim
3
El error mencionado anteriormente en Hibernate parece estar corregido en la versión 3.6.1
Denis Kniazhev
1
@pringlesinn el número de valores en una cláusula IN depende de su DBMS
Tim Büthe
funciona en JPA 1.0 (y no es obligatorio rodear entre paréntesis, pero para mayor legibilidad debería hacerlo)
Javier Larios
¿Qué pasa si quieres => item.name en (como: nombres)
dzgeek
3

El límite de Oracle es 1000 parámetros. El problema se ha resuelto mediante hibernación en la versión 4.1.7, aunque al dividir la lista de parámetros pasados ​​en conjuntos de 500, consulte JIRA HHH-1123

Ashish Thukral
fuente
1
Desafortunadamente, esto no se resolvió. El ticket se marcó como resuelto, pero el equipo de Hibernate no solucionó el problema (como se muestra en los comentarios).
Druckles
@Druckles um ¿dónde? No veo ningún comentario anterior a 2016. Y esos fueron solo dos comentarios que no dicen prácticamente nada más que el habitual "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡11 !!!! No ha dado ninguna razón para confiar en el informe de error resuelto.
seekchengine27
@ seekchengine27 Dije que el informe no se resolvió, a pesar de que estaba marcado como resuelto. La resolución fue, como informó Steve Ebersole: "La resolución de esto es que simplemente vamos a advertir a los usuarios a través del registro cuando se detecte esta condición". Los comentarios de Noel Trout en 2012 explican por qué esto no es suficiente.
Druckles
En otras palabras, esta respuesta es incorrecta o, en el mejor de los casos, engañosa.
Druckles