【问题标题】:Testing: Incompatibility between MySQL and H2测试:MySQL和H2不兼容
【发布时间】:2019-11-04 16:56:06
【问题描述】:

我正在尝试使用 H2 测试我的 JPA 原生 @Query。 我的原生查询如下:

  @Query(
      value = "SELECT * FROM accounts " +
              " WHERE 'account_name' LIKE LOWER(CONCAT('%', COALESCE(:searchTerm, ''), '%')) ",
      countQuery = "SELECT count(*) FROM accounts " +
                   " WHERE 'account_name' LIKE LOWER(CONCAT('%', COALESCE(:searchTerm, ''), '%')) ",
      nativeQuery = true
  )

在编写单元测试时,我收到以下 H2 错误:

原因:org.h2.jdbc.JdbcSQLException:找不到表“ACCOUNTS”; SQL 语句:SELECT * FROM accounts WHERE 'aws_account_name' LIKE LOWER(CONCAT('%', COALESCE(?, ''), '%')) 限制? [42102-197]

我可以通过更改我的 SQL 语法将表名放在双引号中来修复 H2 错误:

  @Query(
      value = "SELECT * FROM \"accounts\" " +
              " WHERE 'account_name' LIKE LOWER(CONCAT('%', COALESCE(:searchTerm, ''), '%')) ",
      countQuery = "SELECT count(*) FROM \"accounts\" " +
                   " WHERE 'account_name' LIKE LOWER(CONCAT('%', COALESCE(:searchTerm, ''), '%')) ",
      nativeQuery = true
  )

但是,然后我的 MySQL(实际非测试环境)抱怨:

Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL 语法;检查与您的 MySQL 服务器相对应的手册 在 '"accounts" WHERE 附近使用正确语法的版本 'account_name' LIKE LOWER(CONCAT('%', COALESCE('ab', ''), ' 在第 1 行

如何使用 MySQL 和 H2 测试这个原生查询?

我使用本机查询而不是 JPQL 的原因是因为我需要在不区分大小写的情况下进行搜索并允许“包含”匹配。

【问题讨论】:

    标签: java mysql jpa h2


    【解决方案1】:

    默认情况下,MySQL 将双引号括起来的标记识别为 字符串文字,而不是 标识符(即表名或列名)。

    如果我们修改 MySQL sql_mode 以包含 ANSI_QUOTES,那么用双引号括起来的标记将被视为 标识符。但这会导致 SQL 中出现问题,其中字符串文字用双引号而不是 SQL 标准的单引号括起来。

    如果 H2 兼容模式设置为 MySQL,那么我们应该能够使用正常的 MySQL 反引号字符来转义标识符。例如

     SELECT *
       FROM `accounts`
            ^        ^
    

    另外,MySQL 不会反对这种结构:

    WHERE 'aws_account_name' LIKE
          ^                ^
    

    但用单引号括起来,MySQL 将标记 'aws_account_name' 视为 字符串文字,而不是对列的引用。

    如果这应该是列名,我们可以在列引用周围使用 MySQL 反引号字符。

    为了减少混淆并使未来的读者更容易阅读,我们通常喜欢限定列引用,即使在没有严格要求的情况下也是如此。例如,使用短表别名:

     SELECT t.*
       FROM `accounts` t
      WHERE t.`aws_account_name` LIKE ...
    

    【讨论】:

    • 当我使用反引号作为表名并具有以下 application.properties 时,似乎仍然对我不起作用:spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 ;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL 仍然得到: 原因:org.h2.jdbc.JdbcSQLException:找不到表“ACCOUNTS”;不确定 MySQL 兼容模式是否在测试中被选中,或者是否是其他原因。
    • 大成功,哈哈!在浏览了 H2 MySQL 兼容性文档并修改了 application.properties 选项后,我意识到我的 pom.xml 中有一个稍旧版本的 H2 依赖项。从 1.4.197 升级到 1.4.199 后一切正常!谢谢!
    猜你喜欢
    • 2014-07-28
    • 2019-06-10
    • 2013-11-16
    • 2017-09-27
    • 2015-01-17
    • 2019-08-15
    • 2013-01-01
    • 2013-12-11
    • 2014-07-19
    相关资源
    最近更新 更多