JPQL IN子句:Java数组(或列表、集合)?

133

我想从我们的数据库中加载所有具有文本标签设置为任意少量但任意值的对象。在SQL中处理这个问题的逻辑方法是构建一个“IN”子句。JPQL允许使用IN,但似乎需要直接指定每个参数(例如,“in(:in1,:in2,:in3)”)。

是否有一种方式可以指定一个数组、列表(或其他容器),以便展开成一个IN子句的值?

3个回答

238

我不确定在JPA 1.0中是否可以,但您可以在JPA 2.0中传递一个Collection

String qlString = "select item from Item item where item.name IN :names"; 
Query q = em.createQuery(qlString, Item.class);

List<String> names = Arrays.asList("foo", "bar");

q.setParameter("names", names);
List<Item> actual = q.getResultList();

assertNotNull(actual);
assertEquals(2, actual.size());

使用 EclipseLink 进行测试。对于 Hibernate 3.5.1,您需要使用括号将参数括起来:

String qlString = "select item from Item item where item.name IN (:names)";

但这是一个错误,前面示例中的JPQL查询是有效的JPQL。请参见HHH-5126


5
在 "in clause" 中使用的名称数量是否有最大限制? - Gondim
3
Hibernate之前提到的漏洞在3.6.1版本中似乎已经修复。 - Denys Kniazhev-Support Ukraine
1
@pringlesinn IN 子句中值的数量取决于您的 DBMS。 - Tim Büthe
如果你想要的是 item.name 在 (类似于:names) 中,该怎么办? - dzgeek
1
不要忘记,如果仍然不起作用(例如java.sql.SQLSyntaxErrorException: ORA-00936: missing expression),请勿将“in (<args...>)”子句与空的<args...>列表一起使用,因为这是无效的。 - Pfiver
显示剩余2条评论

3

我在使用这种sql时遇到了问题,我在IN子句中传递了一个空列表(始终检查列表是否为空)。也许我的做法会帮助到其他人。


3

Oracle数据库只能支持1000个参数。通过将传递的参数列表分成500个一组,Hibernate在版本4.1.7中已经解决了这个问题。 详见JIRA HHH-1123


2
不幸的是,这个问题没有得到解决。工单被标记为已解决,但是(根据评论所示)Hibernate团队并没有修复这个问题。 - Druckles
@Druckles 嗯,哪里?我没有看到任何早于2016年的评论。而且那些只有两个评论,几乎什么都没说,除了通常的互联网“帮帮忙!!!11!!!”。你没有给出任何理由相信错误报告已经解决。 - searchengine27
@searchengine27 我说报告没有解决,尽管它被标记为已解决。正如Steve Ebersole所报道的那样,解决方法是:“当检测到此条件时,我们只需通过日志警告用户即可。” 2012年Noel Trout的评论进一步阐述了为什么这不足够。 - Druckles
换句话说,这个答案是错误的,或者最多也只能算是误导性的。 - Druckles

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