我正在尝试通过使用“:”字符的 JPA 运行本机查询。特定实例在查询中使用 MySQL 用户变量:
SELECT foo, bar, baz,
@rownum:= if (@id = foo, @rownum+1, 1) as rownum,
@id := foo as rep_id
FROM
foo_table
ORDER BY
foo,
bar desc
JPA 代码:
Query q = getEntityManager().createNativeQuery(query, SomeClass.class);
return q.getResultList();
但是,这给了我一个例外,即不允许在“:”后面添加空格。我尝试过用反斜杠转义它们,我尝试过通过将它们加倍来转义它们。有没有办法真正做到这一点,或者我可以吗?
在本机 JPA 查询中使用 postgresql json 函数时,我遇到了类似的经历。
select * from component where data ::json ->> ?1 = ?2
JPA 将抛出错误,表明我尚未设置命名参数:json。
解决方案:
"select * from component where data \\:\\:json ->> ?1 = ?2"
我不知道在查询中转义冒号字符的标准方法,该字符显然被解释为命名参数前缀,从而使查询解析器感到困惑。
我的建议是如果可能的话创建并使用 SQL 函数。根据您的提供商的不同,可能还有其他选项(例如使用另一个字符并在拦截器中用
:
替换所选字符),但至少前面的建议将使您的 JPA 代码在提供商之间保持可移植性。
PS:如果您使用 Hibernate,HHH-1237 上附有一个非常旧的补丁。
更新: JPA 1.0 规范中有一个关于命名参数和本机查询的“有趣”段落:
3.6.3 命名参数
命名参数是一个标识符 以“:”符号为前缀。 命名参数区分大小写。
命名参数遵循以下规则 第 4.4.1 节中定义的标识符。 命名参数的使用适用于Java Persistence查询 语言,并且没有定义 原生查询。仅限位置 参数绑定可以便携使用 用于本机查询。
传递给的参数名称
setParameter
的方法 API 不包含“:”前缀。Query
这不会真正帮助您,但您的情况强烈暗示本机查询中的“:”甚至不应该被考虑(至少没有办法逃避它或禁用它检测)。
我在使用 hibernate-5.6.15.Final 时遇到了同样的问题,经过一番调试后,我发现在本机查询中转义 : 字符的方法是添加另一个 : 字符。
你可以尝试:
SELECT foo, bar, baz,
@rownum::= if (@id = foo, @rownum+1, 1) as rownum,
@id ::= foo as rep_id
FROM
foo_table
ORDER BY
foo,
bar desc
试试这个:
String query =
"SELECT foo, bar, baz,
@rownum \\\\:= if (@id = foo, @rownum+1, 1) as rownum,
@id \\\\:= foo as rep_id
FROM
foo_table
ORDER BY
foo,
bar desc -- escape='\' ";
Query q = getEntityManager().createNativeQuery(query, SomeClass.class);
return q.getResultList();