Ajout d'une liste de clauses IN à une requête JPA


125

J'ai construit un NamedQuery qui ressemble à ceci:

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

Ce que je veux faire, c'est remplir le paramètre: inclList avec une liste d'éléments au lieu d'un élément. Par exemple, si j'ai un new List<String>() { "a", "b", "c" }comment puis-je obtenir cela dans le paramètre: inclList? Cela ne me permet de codifier qu'une seule chaîne. Par exemple:

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

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

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

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

Je sais que je pourrais simplement créer une chaîne et construire toute la requête à partir de cela, mais je voulais éviter la surcharge. Existe-t-il une meilleure façon de le faire?

Question connexe: si la liste est très grande, existe-t-il un bon moyen de créer une requête comme celle-ci?


Ceci est un double de stackoverflow.com/questions/1557085/… mais ce fil fournit des réponses utiles.
Mike Ryan

Réponses:


182

Lors de l'utilisation INavec un paramètre à valeur de collection, vous n'avez pas besoin (...):

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

6
Non ... je mon cas son contraire. Si j'utilise: inclList, cela ne fonctionne pas. Si j'utilise IN (: inclList), cela fonctionne.
Gunjan Shah

1
Notez également que le type de votre paramètre doit être une collection (pas un tableau) d'objets. Les objets doivent correspondre au type du champ. .toString () ne remplace pas la classe String
dube

2
Je pense que c'est quelque chose qui a changé avec les versions d'Hibernate, pour autant que je me souvienne, j'ai eu une erreur lorsque je n'ai pas de paranthèse autour de la variable lors de l'utilisation de IN. Étrange si ce n'est pas rétrocompatible ..
Tobb

1
Il s'agissait en effet d'un bogue de mise en veille prolongée (le besoin de parenthèses) qui a été corrigé dans la version 3.6.1
Mat

1
Pour une question connexe: En cas de liste très longue, il pourrait y avoir des limitations pour la mise en œuvre. Par exemple, oracle 11g. max. 1000 éléments de liste en tant que paramètre sont possibles. Une solution de contournement consiste à découper la liste en sous-listes et à collecter les résultats. JPA lui-même ne limite pas la taille de la liste.
Mahttias Schrebiér

81

Le format de requête JPA approprié serait:

el.name IN :inclList

Si vous utilisez une ancienne version d'Hibernate comme fournisseur, vous devez écrire:

el.name IN (:inclList)

mais c'est un bug ( HHH-5126 ) (EDIT: qui a été résolu maintenant).


5
Merci d'avoir distingué les anciennes versions d'Hibernate use ()
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();
    }

Fonctionne pour moi avec JPA 2, Jboss 7.0.2


9

Vous devez convertir Listcomme indiqué ci-dessous:

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

Thx cette réponse m'a aidé
cabaji99
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.