it-swarm.com.de

Durchführen einer "IN" -Abfrage mit Hibernate

Ich habe eine Liste von IDs in einem String und möchte Hibernate verwenden, um die Zeilen mit diesen IDs abzurufen. TrackedItem ist eine Hibernate/JPA-Entität (sorry, wenn die Namen hier gemischt werden).

Mein Code lautet:

String idsText = "380, 382, 386";
ArrayList<Long> ids = new ArrayList<Long>();

for (String i : idsText.split(","))
{
    ids.add(Long.getLong(i));
}

List<TrackedItem> items = TrackedItem.find("id IN (?)", ids).fetch();

Aber das schlägt fehl: JPAQueryException occured : Error while executing query from models.TrackedItem where id IN (?): Java.util.ArrayList cannot be cast to Java.lang.Long

Wie kann ich den IN-Teil funktionieren lassen? Vielen Dank.

31
Amy B

Die Syntax Ihrer JPQL-Abfrage ist falsch. Verwenden Sie entweder (mit einem Positionsparameter):

List<Long> ids = Arrays.asList(380L, 382L, 386L);
Query query = em.createQuery("FROM TrackedItem item WHERE item.id IN (?1)");
query.setParameterList(1, ids)
List<TrackedItem> items = query.getResultList();

Oder (mit einem benannten Parameter):

List<Long> ids = Arrays.asList(380L, 382L, 386L);
Query query = em.createQuery("FROM TrackedItem item WHERE item.id IN :ids");
query.setParameterList("ids", ids)
List<TrackedItem> items = query.getResultList();

Nachfolgend die relevanten Abschnitte der JPA 1.0-Spezifikation zu Parametern:

4.6.4.1 Positionsparameter

Die folgenden Regeln gelten für Positionsparameter.

  • Eingabeparameter werden durch das Fragezeichen (?) Gefolgt von einer Ganzzahl gekennzeichnet. Zum Beispiel: ?1.
  • Die Eingangsparameter sind ab 1 nummeriert.
    Beachten Sie, dass derselbe Parameter in der Abfragezeichenfolge mehrmals verwendet werden kann und dass die Reihenfolge der Verwendung von Parametern in der Abfragezeichenfolge nicht mit der Reihenfolge der Positionsparameter übereinstimmen muss.

4.6.4.2 Benannte Parameter

Ein benannter Parameter ist ein Bezeichner, dem das Symbol ":" vorangestellt ist. Es folgt den Regeln für Bezeichner, die in Abschnitt 4.4.1 definiert sind. Bei benannten Parametern wird die Groß- und Kleinschreibung beachtet.

Beispiel:

SELECT c
FROM Customer c
WHERE c.status = :stat

Abschnitt 3.6.1 beschreibt die API zum Binden benannter Abfrageparameter

58
Pascal Thivent

Wenn Sie das Pech haben, ältere Nicht-JPA-Ruhezustände zu verwenden, sollte dies für Sie funktionieren:

Query query = session.createQuery("FROM TrackedItem item WHERE item.id IN (:items)");
query.setParameterList("items", Arrays.asList(380L, 382L, 386L));

@SuppressWarnings("unchecked")
List<TrackedItem> results = query.list();
10
depsypher

Selbst wenn Ihre Abfrage korrekt ausgeführt wird, kann ein Fehler auftreten, wenn Ihr Abfrageparameter zu viele Werte enthält. 

Eine mögliche Lösung für dieses Problem, wenn Sie Hibernate 5.1 oder neuer verwenden, ist Session.byMultipleIds ().

session
    .byMultipleIds(TrackedItem.class)
    .multiLoad(1L, 2L, 3L);

Weitere Informationen finden Sie unter https://thoughts-on-Java.org/fetch-multiple-entities-id-hibernate/