如何在hibernate本机查询中使用MySQL assign运算符(:=)?

时间:2012-02-27 04:19:19

标签: java mysql hibernate nativequery

我正在使用Hibernate。我写了一些原生查询,因为我需要使用sub select语句。

查询如下所示:

SELECT sub.rownum FROM 
    (SELECT k.`news_master_id` AS id, @row := @row + 1 AS rownum 
        FROM keyword_news_list k 
        JOIN (SELECT @row := 0) r 
        WHERE k.`keyword_news_id` = :kid
    ORDER BY k.`news_master_id` ASC) AS sub 
WHERE sub.id  = :nid

当我像这样运行此查询时:

sessionFactory.getCurrentSession()
    .createSQLQuery(query)
    .setParameter("kid", kid)
    .setParameter("nid", nid)
    .uniqueResult();

出现此异常:

org.hibernate.QueryException: Space is not allowed after parameter prefix ':' ....

这可能是因为:=运算符。我发现了一些Hibernate issue。这个问题仍然存在。这个问题没有解决办法吗?

7 个答案:

答案 0 :(得分:24)

请注意,HHH-2697现在已针对Hibernate 4.1.3修复,并在Hibernate 4.3.8.Final上进行了测试;你必须用反斜杠逃脱:

SELECT k.`news_master_id` AS id, @row \:= @row + 1 AS rownum 
    FROM keyword_news_list k 
    JOIN (SELECT @row \:= 0) r 
    WHERE k.`keyword_news_id` = :kid
ORDER BY k.`news_master_id` ASC

答案 1 :(得分:15)

对于我们这些无法跳转到Hibernate 4.1.3的人来说,这是另一种解决方案 只需在查询中使用/*'*/:=/*'*/即可。 Hibernate代码将'之间的所有内容视为字符串(忽略它)。另一方面,MySQL会忽略blockquote中的所有内容,并将整个表达式计算为一个assignement运算符 我知道它快速而且肮脏,但是没有存储过程,拦截器等就可以完成工作。

答案 2 :(得分:5)

你可以实现这是一种稍微不同的方式..你需要用其他东西替换:运算符(比如'|'char)并在你的拦截器中替换'|'与:。

这样,hibernate不会试图认为:是一个参数但是会忽略它

对于拦截器逻辑,您可以参考hibernate manual

这对我使用MySQL 5很有用。

记住,这个替换:必须只对':='和其他MySQL特定的要求做..不要试图替换:为param-placeholders。 (然后hibernate将无法识别params)

答案 3 :(得分:0)

我更喜欢包含Spring JDBC并执行查询而不是对抗Hibernate拦截器。

答案 4 :(得分:0)

<{3>} 斯坦尼斯拉夫提供了除拦截器以外的其他选择来解决此问题

答案 5 :(得分:0)

如果您的SQL文件远离Java代码,请尝试这段代码。为了获得正确数量的转义斜杠而发挥了很多作用:

String sqlPattern = FileUtils.readFile(this.getClass(), /sql/my_query.sql");
sqlPattern = sqlPattern.replaceAll(":=", "\\\\:=");
Query query = entityManager.createNativeQuery(sqlPattern);

答案 6 :(得分:-5)

我想在=之后应该没有空格,运算符应该写成= :(没有任何空格)