【问题标题】:How can I use MySQL assign operator(:=) in hibernate native query?如何在休眠本机查询中使用 MySQL 分配运算符(:=)?
【发布时间】:2012-03-16 15:08:20
【问题描述】:

我正在使用休眠。我写了一些原生查询,因为我需要使用 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。这个问题仍然是开放的。这个问题没有解决办法吗?

【问题讨论】:

标签: java mysql hibernate nativequery


【解决方案1】:

如果您的 SQL 文件远离 Java 代码 - 请尝试这段代码。为了获得正确数量的转义斜线,玩了很多:

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

【讨论】:

    【解决方案2】:

    请注意,HHH-2697 现在已针对 Hibernate 4.1.3 修复,您现在可以使用反斜杠转义:

    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
    

    【讨论】:

    • 使用 Hibernate 4.3.7 只有一个反斜杠就足够了,例如PG 9.3 查询select f( p_tst \:= 1 )(Java 字符串中可能有两个转义它们)
    • 这应该被标记为正确答案,它有效且容易得多。
    • 工作正常,在 @Query( value = "<...>" , nativeQuery = true) 的 spring jpa 存储库中,我必须在引号内使用双反斜杠 \\:= 以避免编译时错误。
    【解决方案3】:

    in Hibernate exception on encountering mysql := operatorStanislav 提供了拦截器以外的另一个选项来解决此问题

    【讨论】:

      【解决方案4】:

      为我们这些无法跳转到 Hibernate 4.1.3 的人提供另一种解决方案。
      只需在查询中使用/*'*/:=/*'*/。 Hibernate 代码将' 之间的所有内容视为字符串(忽略它)。另一方面,MySQL 将忽略块引用中的所有内容,并将整个表达式评估为赋值运算符。
      我知道它又快又脏,但它可以在没有存储过程、拦截器等的情况下完成工作。

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

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

          拦截器逻辑可以参考hibernate manual

          这对我使用 MySQL 5 有效。

          记住,这种 : 的替换必须只针对 ':=' 和其他 MySQL 特定要求。不要尝试替换 : 的参数占位符。 (此时休眠将无法识别参数)

          【讨论】:

          • 冬眠有多蠢啊?我可以想象编码器会走。不,SQL 中怎么可能有冒号。没有机会!让我们让它没有转义机制!
          • 抱歉,我对不得不工作有点生气。上面的解决方案只有在你只有一把锤子的情况下。您也可以使用 \: 来转义冒号,但在我的情况下,它破坏了每个命名参数(它们刚刚停止工作。)
          【解决方案7】:

          我猜=后面不应该有空格,操作符应该写成=:(不带空格)

          【讨论】:

            猜你喜欢
            • 2010-12-26
            • 2017-10-08
            • 1970-01-01
            • 2012-12-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-29
            • 2011-08-10
            相关资源
            最近更新 更多