将IN子句列表添加到JPA查询


124

我建立了一个NamedQuery,看起来像这样:

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

我想做的是用一个项目列表而不是一个项目填充参数:inclList。例如,如果我有一个方法,new List<String>() { "a", "b", "c" }如何在:inclList参数中得到它?它只允许我编入一个字符串。例如:

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

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

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

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

我知道我可以构建一个字符串并从中构建整个查询,但是我想避免开销。有更好的方法吗?

相关问题:如果列表很大,有什么好的方法来构建这样的查询?


这是stackoverflow.com/questions/1557085/…的副本,但是此线程提供了有用的答案。
Mike Ryan

Answers:


181

IN与集合值参数一起使用时,您不需要(...)

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

6
不,我的情况与之相反。如果我使用:inclList,则它不起作用。如果我使用IN(:inclList),那么它将起作用。
Gunjan Shah 2012年

1
另请注意:参数的类型必须是对象的集合(而不是数组)。对象必须与字段的类型匹配。.toString()不能替代String类
dube

2
我认为这是随着Hibernate的版本而改变的,据我所记得,当使用IN时,变量周围没有括号时,我得到了一个错误。如果不向后兼容,那就太奇怪了
。– Tobb

1
这确实是一个冬眠错误(需要括号),该错误已在3.6.1
Mat Mat

1
对于相关问题:如果列表很大,则实现可能会受到限制。例如oracle 11g。最高 可能有1000个列表元素作为参数。一种解决方法是将列表切成subLists并收集结果。JPA本身并不限制列表的大小。
MahttiasSchrebiér16年

81

正确的JPA查询格式为:

el.name IN :inclList

如果您使用的是较早版本的Hibernate作为提供程序,则必须编写:

el.name IN (:inclList)

但这是一个错误(HHH-5126)(编辑:到现在已解决)。


5
感谢您区分旧版本的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();
    }

适用于JPA 2,Jboss 7.0.2


9

您必须转换List为如下所示:

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

谢谢
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.