Agregar lista de cláusulas IN a una consulta JPA

125

He creado una NamedQuery que se ve así:

@NamedQuery(name = "EventLog.viewDatesInclude",
        query = "SELECT el FROM EventLog el WHERE el.timeMark >= :dateFrom AND "
        + "el.timeMark <= :dateTo AND "
        + "el.name IN (:inclList)")

Lo que quiero hacer es completar el parámetro: inclList con una lista de elementos en lugar de un elemento. Por ejemplo, si tengo un new List<String>() { "a", "b", "c" }¿cómo lo consigo en el parámetro: inclList? Solo me permite codificar una cadena. Por ejemplo:

setParameter("inclList", "a") // works

setParameter("inclList", "a, b") // does not work

setParameter("inclList", "'a', 'b'") // does not work

setParameter("inclList", list) // throws an exception

Sé que podría simplemente construir una cadena y construir la consulta completa a partir de eso, pero quería evitar la sobrecarga. ¿Existe una forma mejor de hacer esto?

Pregunta relacionada: si la lista es muy grande, ¿hay alguna buena forma de crear consultas como esa?

AlanObject
fuente
Este es un duplicado de stackoverflow.com/questions/1557085/… pero este hilo proporciona respuestas útiles.
Mike Ryan

Respuestas:

182

Cuando se usa INcon un parámetro con valor de colección, no necesita (...):

@NamedQuery(name = "EventLog.viewDatesInclude", 
    query = "SELECT el FROM EventLog el WHERE el.timeMark >= :dateFrom AND " 
    + "el.timeMark <= :dateTo AND " 
    + "el.name IN :inclList") 
axtavt
fuente
6
No ... yo mi caso es lo contrario. Si uso: inclList, entonces no funciona. Si uso IN (: inclList), entonces funciona.
Gunjan Shah
1
También tenga en cuenta la mención: el tipo de su parámetro tiene que ser una colección (no una matriz) de objetos. Los objetos deben coincidir con el tipo de campo. .toString () no sustituye a la clase String
dube
2
Creo que esto es algo que ha cambiado con las versiones de Hibernate, por lo que puedo recordar, he recibido un error al no tener la parátesis alrededor de la variable al usar IN. Extraño si no es compatible con versiones anteriores.
Tobb
1
De hecho, este fue un error de hibernación (la necesidad de paréntesis) que se corrigió en 3.6.1
Mat
1
Para una pregunta relacionada: En caso de una lista muy grande, podrían existir limitaciones para la implementación. Por ejemplo, oráculo 11g. máx. Son posibles 1000 elementos de lista como parámetro. Una solución alternativa es dividir la lista en subListas y recopilar los resultados. JPA en sí no restringe el tamaño de la lista.
Mahttias Schrebiér
81

El formato de consulta JPA adecuado sería:

el.name IN :inclList

Si está utilizando una versión anterior de Hibernate como proveedor, debe escribir:

el.name IN (:inclList)

pero eso es un error ( HHH-5126 ) (EDITAR: que ya se ha resuelto).

Jose ferrer
fuente
5
Gracias por distinguir las versiones anteriores del uso de Hibernate ()
Rob L
32
public List<DealInfo> getDealInfos(List<String> dealIds) {
        String queryStr = "SELECT NEW com.admin.entity.DealInfo(deal.url, deal.url, deal.url, deal.url, deal.price, deal.value) " + "FROM Deal AS deal where deal.id in :inclList";
        TypedQuery<DealInfo> query = em.createQuery(queryStr, DealInfo.class);
        query.setParameter("inclList", dealIds);
        return query.getResultList();
    }

Funciona para mí con JPA 2, Jboss 7.0.2

usuario1114134
fuente
9

Debe convertir a Listcomo se muestra a continuación:

    String[] valores = hierarquia.split(".");       
    List<String> lista =  Arrays.asList(valores);

    String jpqlQuery = "SELECT a " +
            "FROM AcessoScr a " +
            "WHERE a.scr IN :param ";

    Query query = getEntityManager().createQuery(jpqlQuery, AcessoScr.class);                   
    query.setParameter("param", lista);     
    List<AcessoScr> acessos = query.getResultList();
Wesley Rocha
fuente
Gracias, esta respuesta me ayudó
cabaji99