我正在尝试通过使用“:”字符的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();
但是,这给了我一个例外,即不允许用空格跟随':'。我已经尝试用反斜杠逃避它们,我已经尝试通过将它们加倍来逃避它们。有没有办法真正做到这一点,还是我是SOL?
答案 0 :(得分:40)
在本机JPA查询中使用postgresql json function时,我遇到了类似的经历。
select * from component where data ::json ->> ?1 = ?2
JPA会抛出我没有设置命名参数的错误:json。
解决方案:
select * from component where data \\:\\:json ->> ?1 = ?2
答案 1 :(得分:1)
我不知道在查询中转义冒号字符的标准方法,该查询显然被解释为命名参数前缀,从而混淆了查询解析器。
我的建议是尽可能创建和使用SQL函数。根据您的提供商,可能还有其他选项(例如使用另一个字符并在拦截器中用:
替换所选字符)但至少之前的建议会使您的JPA代码在提供商之间保持可移植性。
PS:如果你正在使用Hibernate,那么HHH-1237附有一个非常旧的补丁。
更新: JPA 1.0规范中有一个关于命名参数和本机查询的“有趣”段落:
3.6.3命名参数
命名参数是标识符 以“:”符号为前缀。 命名参数区分大小写。
命名参数遵循规则 第4.4.1节中定义的标识符。 命名参数的使用适用于Java Persistence查询 语言,并没有定义 原生查询。只有位置 可以便携地使用参数绑定 用于原生查询。
传递给的参数名称
setParameter
的{{1}}种方法 API不包含“:”前缀。
这对你没有用,但是你的情况强烈暗示原生查询中的“:”甚至不应该被考虑(至少没有办法逃脱它或禁用它检测)。
答案 2 :(得分:-1)
试试这个:
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();