Incluindo Lista de Cláusulas IN em uma Consulta JPA

124

Eu criei uma NamedQuery que se parece com isso:

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

O que eu quero fazer é preencher o parâmetro: inclList com uma lista de itens em vez de um item. Por exemplo, se eu tiver um, new List<String>() { "a", "b", "c" }como faço para obtê-lo no parâmetro: inclList? Apenas me permite codificar uma string. Por exemplo:

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

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

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

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

Eu sei que eu poderia criar uma string e criar toda a consulta a partir disso, mas queria evitar a sobrecarga. Existe um jeito melhor de fazer isso?

Pergunta relacionada: se a Lista for muito grande, existe alguma maneira de criar consultas como essa?

AlanObject
fonte
Esta é uma duplicata do stackoverflow.com/questions/1557085/…, mas este tópico fornece respostas úteis.
Mike Ryan

Respostas:

181

Ao usar INcom um parâmetro com valor de coleção, você não precisa de (...):

@NamedQuery(name = "EventLog.viewDatesInclude", 
    query = "SELECT el FROM EventLog el WHERE el.timeMark >= :dateFrom AND " 
    + "el.timeMark <= :dateTo AND " 
    + "el.name IN :inclList") 
axtavt
fonte
6
Não ... eu meu caso é o contrário. Se eu usar: inclList, não está funcionando. Se eu usar IN (: inclList), ele funcionará.
Gunjan Shah
1
Observe também a menção: o tipo do seu parâmetro deve ser uma coleção (não uma matriz) de objetos. Os objetos devem corresponder ao tipo do campo. .toString () não substitui a classe String
dube
2
Eu acho que isso mudou com as versões do Hibernate, pelo que me lembro, recebi um erro ao não ter parênteses em torno da variável ao usar IN. Estranho se não é compatível com versões anteriores ..
több
1
Este foi realmente um bug de hibernação (a necessidade de parênteses) que foi corrigido em 3.6.1
Mat
1
Para questões relacionadas: No caso de uma lista muito grande, pode haver limitações para a implementação. Por exemplo, oracle 11g. máx. São possíveis 1000 elementos da lista como parâmetro. Uma solução alternativa é cortar a lista em subListas e coletar os resultados. A própria JPA não restringe o tamanho da lista.
Mahttias Schrebiér
81

O formato de consulta JPA adequado seria:

el.name IN :inclList

Se você estiver usando uma versão mais antiga do Hibernate como seu provedor, precisará escrever:

el.name IN (:inclList)

mas isso é um bug ( HHH-5126 ) (EDIT: que foi resolvido até agora).

Jose Ferrer
fonte
5
Obrigado por distinguir as versões mais antigas do uso do Hibernate ()
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();
    }

Funciona para mim com o JPA 2, Jboss 7.0.2

user1114134
fonte
9

Você deve converter para Listcomo mostrado abaixo:

    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
fonte
Thx esta resposta ajudou-me #
11551 Dec1