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

161

我已经构建了一个类似于这样的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

我知道我可以只是构建一个字符串并从那里构建整个查询,但我想避免额外的开销。有没有更好的方法来做到这一点?

相关问题:如果列表非常大,是否有任何很好的方法来构建这样的查询?


这是 https://dev59.com/zXI_5IYBdhLWcg3wBuX3 的重复,但这个线程提供了有用的答案。 - Mike Ryan
4个回答

219

使用集合参数时,IN 不需要使用 (...)

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

9
不是的……在我的情况下相反。如果我使用 ":inclList",它不起作用。如果我使用 "IN (:inclList)",它就能工作。 - Gunjan Shah
2
还要注意提到:您的参数类型必须是对象的集合(而不是数组)。对象必须与字段的类型匹配。.toString()不能替代String类。 - dube
2
我认为这是与 Hibernate 版本有关的变化,据我所记得,当在使用 IN 时没有将括号括起来时,我曾经遇到过错误。如果它不向后兼容,那就很奇怪了。 - Tobb
1
这确实是一个 Hibernate 的 bug(需要括号),已在 3.6.1 中修复。 - Mat
2
针对相关问题:在实现中可能存在非常大的列表限制。例如,Oracle 11g最多只能有1000个列表元素作为参数。一种解决方法是将列表分割成子列表并收集结果。JPA本身不限制列表大小。 - Mahttias Schrebiér
它确实起作用了。谢谢你。现在,我该如何将其变成可选过滤器?:inclList IS NULL OR el.name IN : inclList会抛出QuerySyntaxException: unexpected AST node,因为它也在第一部分连接整个列表。 - Guilherme Taffarel Bergamin

106

适当的JPA查询格式应为:

el.name IN :inclList

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

el.name IN (:inclList)

但是那只是一个bug (HHH-5126)(编辑:此问题现已得到解决)。


6
感谢您区分旧版Hibernate的使用方法 ()。 - Rob L

37
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对我有效


感谢您展示了一个简洁但完整的示例。 - Queeg

21
你应该按照以下示例转换为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();

谢谢,这个答案帮了我。 - cabaji99
这是最佳答案。 - Sami Haroon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接