Hinzufügen einer IN-Klauselliste zu einer JPA-Abfrage

124

Ich habe eine NamedQuery erstellt, die so aussieht:

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

Ich möchte den Parameter: includeList mit einer Liste von Elementen anstelle eines Elements ausfüllen. Wenn ich zum Beispiel eine habe, new List<String>() { "a", "b", "c" }wie erhalte ich das im Parameter: inclList? Ich kann nur eine Zeichenfolge codieren. Beispielsweise:

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

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

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

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

Ich weiß, ich könnte einfach einen String erstellen und daraus die gesamte Abfrage erstellen, aber ich wollte den Overhead vermeiden. Gibt es einen besseren Weg, dies zu tun?

Verwandte Frage: Wenn die Liste sehr groß ist, gibt es eine gute Möglichkeit, eine solche Abfrage zu erstellen?

AlanObject
quelle
Dies ist ein Duplikat von stackoverflow.com/questions/1557085/…, aber dieser Thread bietet nützliche Antworten.
Mike Ryan

Antworten:

181

Bei Verwendung INmit einem Parameter mit Sammlungswert benötigen Sie nicht (...):

@NamedQuery(name = "EventLog.viewDatesInclude", 
    query = "SELECT el FROM EventLog el WHERE el.timeMark >= :dateFrom AND " 
    + "el.timeMark <= :dateTo AND " 
    + "el.name IN :inclList") 
axtavt
quelle
6
Nein ... ich mein Fall ist das Gegenteil. Wenn ich: includeList benutze, funktioniert es nicht. Wenn ich IN (: inclList) verwende, funktioniert es.
Gunjan Shah
1
Beachten Sie auch Folgendes: Der Typ Ihres Parameters muss eine Sammlung (kein Array) von Objekten sein. Die Objekte müssen dem Feldtyp entsprechen. .toString () ist kein Ersatz für die Klasse String
dube
2
Ich denke, dies hat sich mit den Versionen von Hibernate geändert, soweit ich mich erinnern kann, ist bei der Verwendung von IN ein Fehler aufgetreten, wenn die Paranthesis um die Variable nicht vorhanden ist. Seltsam, wenn es nicht abwärtskompatibel ist ..
Tobb
1
Dies war in der Tat ein Fehler im Ruhezustand (die Notwendigkeit von Klammern), der in 3.6.1
Mat
1
Für verwandte Fragen: Bei sehr großen Listen kann es zu Einschränkungen bei der Implementierung kommen. ZB Orakel 11g. max. 1000 Listenelemente als Parameter sind möglich. Eine Problemumgehung besteht darin, die Liste in Unterlisten zu zerlegen und die Ergebnisse zu sammeln. JPA selbst schränkt die Listengröße nicht ein.
Mahttias Schrebiér
81

Das richtige JPA-Abfrageformat wäre:

el.name IN :inclList

Wenn Sie eine ältere Version von Hibernate als Provider verwenden, müssen Sie Folgendes schreiben:

el.name IN (:inclList)

aber das ist ein Fehler ( HHH-5126 ) (EDIT: der inzwischen behoben wurde).

Jose Ferrer
quelle
5
Vielen Dank für die Unterscheidung der älteren Versionen von 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();
    }

Funktioniert für mich mit JPA 2, Jboss 7.0.2

user1114134
quelle
9

Sie müssen Listwie folgt konvertieren :

    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
quelle
Diese Antwort hat mir geholfen
cabaji99