如何在 JPA 命名查询的 IN 子句中使用动态参数?

Posted

技术标签:

【中文标题】如何在 JPA 命名查询的 IN 子句中使用动态参数?【英文标题】:How to use a dynamic parameter in a IN clause of a JPA named query? 【发布时间】:2014-02-24 09:21:45 【问题描述】:

我的问题是关于这种查询:

select * from SOMETABLE where SOMEFIELD in ('STRING1','STRING2');

前面的代码在 Sql Developer 中运行良好。 同样的静态查询也可以正常工作并返回一些结果;

Query nativeQuery = em.createNativeQuery(thePreviousQuery,new someResultSet());
return nativeQuery.getResultList();

但是当我尝试参数化这个时,我遇到了一个问题。

final String parameterizedQuery = "select * from SOMETABLE where SOMEFIELD in (?selectedValues)";
Query nativeQuery = em.createNativeQuery(parameterizedQuery ,new someResultSet());
nativeQuery.setParameter("selectedValues","'STRING1','STRING2'");
return nativeQuery.getResultList();

我没有得到任何结果(但控制台中没有错误)。 当我查看日志时,我看到了这样的事情:

select * from SOMETABLE where SOMEFIELD in (?)
bind => [STRING1,STRING2]

我也尝试不使用引号(结果相似)或无序参数(:selectedValues),这会导致这样的错误:

SQL Error: Missing IN or OUT parameter at index:: 1

我最终尝试在参数中直接设置括号,而不是在查询中,但这也不起作用......

我可以在运行时构建我的查询,以匹配第一个(工作)案例,但我宁愿以正确的方式进行;因此,如果有人有想法,我会非常感兴趣地阅读它们!

仅供参考: JPA 1.0 版 甲骨文11G

【问题讨论】:

【参考方案1】:

替换这个:

nativeQuery.setParameter("selectedValues","'STRING1','STRING2'");

List<String> params;
nativeQuery.setParameter("selectedValues",params);

【讨论】:

感谢您的快速答复。不过,我忘了提到我也试过这个,srry:错误 17004 => 无效的列类型。绑定看起来像这样:bind => [[STRING1,STRING2]]【参考方案2】:

JPA 仅在 JPQL 查询中支持将集合用作列表文字参数,而不在本机查询中使用。一些 JPA 提供商支持它作为专有功能,但它不是 JPA 规范的一部分(请参阅https://***.com/a/3145275/1285097)。

本机查询中的命名参数也不属于 JPA 规范。它们的行为取决于持久性提供程序和/或 JDBC 驱动程序。

使用适用于 Oracle 的 JDBC 驱动程序的休眠支持这两个功能。

List<String> selectedValues = Arrays.asList("STRING1", "STRING2");
final String parameterizedQuery = "select * from SOMETABLE where SOMEFIELD in (:selectedValues)";
return em.createNativeQuery(parameterizedQuery)
         .setParameter("selectedValues", selectedValues)
         .getResultList();

【讨论】:

Marc-André,感谢您指出问题。现在我意识到我必须要么使用休眠 - 我不会被允许这样做,我担心 - 要么执行基本的连接。还是谢谢! 据我所知,最好的做法是动态添加到查询中 a ?为列表中的每个元素设置参数,然后单独设置每个参数。这允许 Oracle 在多次使用相同数量的元素的查询时使用其缓存。 对于 Native 查询,参数名称必须是 #selectedValues 而不是 :selectedValues 对于 EclipseLink JPA。 使用适用于 MSSQL 的 jTDS JDBC 驱动程序进行休眠也支持将列表作为本机查询的参数【参考方案3】:

代替:

nativeQuery.setParameter("selectedValues", params);

我不得不使用:

nativeQuery.setParameterList("selectedValues", params);

【讨论】:

setParameterList 方法从何而来? 见docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/…, java.util.Collection) setParameterList 是 Hibernate 特有的功能,在标准 JPA 中不可用【参考方案4】:

这在德比中对我有用。没有“()”的参数。

List<String> selectedValues = Arrays.asList("STRING1", "STRING2");
final String parameterizedQuery = "select * from SOMETABLE where SOMEFIELD in 
:selectedValues";
return em.createNativeQuery(parameterizedQuery)
         .setParameter("selectedValues", selectedValues)
         .getResultList();

【讨论】:

【参考方案5】:

我也遇到了同样的问题。 这就是我所做的:

List<String> sample = new ArrayList<String>();
sample.add("sample1");
sample.add("sample2");

现在您可以在params 中设置示例。

【讨论】:

以上是关于如何在 JPA 命名查询的 IN 子句中使用动态参数?的主要内容,如果未能解决你的问题,请参考以下文章

在本机 sql 查询中使用 IN 子句

JPA JPQL IN 子句:如何在 JPA 中使用 IN 子句?

JPA JPQL IN子句:如何在JPA中使用IN子句?

如何保持 Spring Data JPA 或 Hibernate 中“in”子句中提供的顺序 [重复]

JPA Criteria builder IN 子句查询

如何在使用变量的动态查询中指定 IN 子句?