Aggiunta di un elenco di clausole IN a una query JPA


125

Ho creato una NamedQuery simile a questa:

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

Quello che voglio fare è compilare il parametro: inclList con un elenco di elementi invece di un elemento. Ad esempio, se ho un new List<String>() { "a", "b", "c" }come lo ottengo nel parametro: inclList? Mi consente di codificare solo una stringa. Per esempio:

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

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

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

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

So che potrei semplicemente costruire una stringa e costruire l'intera Query da quella, ma volevo evitare il sovraccarico. C'è un modo migliore per farlo?

Domanda correlata: se l'elenco è molto grande, esiste un buon modo per creare query del genere?


Questo è un duplicato di stackoverflow.com/questions/1557085/… ma questo thread fornisce risposte utili.
Mike Ryan

Risposte:


182

Quando si utilizza INcon un parametro con valori di raccolta non è necessario (...):

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

6
No ... nel mio caso è l'opposto. Se uso: inclList allora non funziona. Se uso IN (: inclList) allora funziona.
Gunjan Shah

1
Nota anche la menzione: il tipo del tuo parametro deve essere una raccolta (non un array) di oggetti. Gli oggetti devono corrispondere al tipo di campo. .toString () non sostituisce la classe String
dube

2
Penso che questo sia qualcosa che è cambiato con le versioni di Hibernate, per quanto posso ricordare ho ricevuto un errore quando non ho la parentesi attorno alla variabile quando si usa IN. Strano se non è retrocompatibile ..
Tobb

1
Questo era davvero un bug di ibernazione (la necessità di parentesi) che è stato corretto in 3.6.1
Mat

1
Per domande correlate: in caso di elenchi molto grandi potrebbero esserci limitazioni per l'implementazione. Ad esempio oracle 11g. max. Sono possibili 1000 elementi della lista come parametro. Una soluzione alternativa è tagliare l'elenco in sottoliste e raccogliere i risultati. JPA stesso non limita la dimensione dell'elenco.
Mahttias Schrebiér

81

Il formato di query JPA corretto sarebbe:

el.name IN :inclList

Se stai utilizzando una versione precedente di Hibernate come provider devi scrivere:

el.name IN (:inclList)

ma questo è un bug ( HHH-5126 ) (EDIT: che è stato risolto ormai).


5
Grazie per aver distinto le versioni precedenti di Hibernate use ()
Rob L

31
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();
    }

Funziona per me con JPA 2, Jboss 7.0.2


9

È necessario convertire in Listcome mostrato di seguito:

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

Grazie a questa risposta mi ha aiutato
cabaji99
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.