gpt4 book ai didi

java - 单元测试中的 jOOQ + Liquibase + H2 结果出现 "schema not found"异常

转载 作者:行者123 更新时间:2023-11-30 02:15:07 25 4
gpt4 key购买 nike

我正在为一些数据访问代码编写单元测试。设置中的关键部分包括:

  • jOOQ 为 CRUD 操作生成工件
  • Liquibase 用于处理架构演变

鉴于此,我正在尝试按如下方式设置测试:

  1. 创建一个java.sql.Connection以使用适当命名的架构初始化H2数据库。 (这里值得注意的是,连接是使用以下 URL 创建的:jdbc:h2:mem:[架构名称];MODE=MySQL;DB_CLOSE_DELAY=-1)。

  2. 使用上述连接,调用 Liquibase 运行更改日志,在数据库架构中创建所有对象

  3. 使用上述连接,创建一个org.jooq.DSLContext,用它可以测试数据访问组件。

抽象类将这三个步骤封装在 @Before 带注释的方法中,测试类扩展此抽象类以利用初始化的 org.jooq.DSLContext 实例。像这样的东西:

abstract class DbTestBase {
protected lateinit var dslContext: DSLContext

private lateinit var connection: Connection

open fun setUp() {
connection = DriverManager.getConnection("jdbc:h2:mem:foo;MODE=MySQL;DB_CLOSE_DELAY=-1")

// invoke Liquibase with this connection instance...

dslContext = DSL.using(connection, SQLDialect.H2)
}

open fun tearDown() {
dslContext.close()

connection.close()
}
}

class MyTest : DbTestBase() {
private lateinit var repository: Repository

@Before override fun setUp() {
super.setUp()

repository = Repository(dslContext)
}

@After override fun tearDown() {
super.tearDown()
}

@Test fun something() {
repository.add(Bar())
}
}

这会导致以下异常:

Caused by: org.h2.jdbc.JdbcSQLException: Schema "foo" not found; SQL statement:
insert into `foo`.`bar` (`id`) values (?) [90079-196]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.command.Parser.getSchema(Parser.java:688)
at org.h2.command.Parser.getSchema(Parser.java:694)
at org.h2.command.Parser.readTableOrView(Parser.java:5535)
at org.h2.command.Parser.readTableOrView(Parser.java:5529)
at org.h2.command.Parser.parseInsert(Parser.java:1062)
at org.h2.command.Parser.parsePrepared(Parser.java:417)
at org.h2.command.Parser.parse(Parser.java:321)
at org.h2.command.Parser.parse(Parser.java:293)
at org.h2.command.Parser.prepareCommand(Parser.java:258)
at org.h2.engine.Session.prepareLocal(Session.java:578)
at org.h2.engine.Session.prepareCommand(Session.java:519)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1204)
at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:73)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:288)
at org.jooq.impl.ProviderEnabledConnection.prepareStatement(ProviderEnabledConnection.java:106)
at org.jooq.impl.SettingsEnabledConnection.prepareStatement(SettingsEnabledConnection.java:70)
at org.jooq.impl.AbstractQuery.prepare(AbstractQuery.java:410)
at org.jooq.impl.AbstractDMLQuery.prepare(AbstractDMLQuery.java:342)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:316)
... 25 more

我可以在重新生成架构时看到 Liquibase 日志记录。此后,我更改了 H2 URL 以创建基于文件的数据库,我能够检查并验证该架构确实存在。

如果您能帮助我发现该方法中的任何错误,我将不胜感激。

最佳答案

经过多次尝试和错误,我能够通过解决两个问题来解决我的问题:

  1. Lukas 区分“数据库”(或“目录”)与“模式”的评论将我推向了正确的方向。尽管这些术语在 MySQL(我的生产数据库)中似乎可以互换使用,但它们在 H2 中却不是。事后看来似乎相当明显,但解决办法是调用 JDBC 调用来手动构建架构,然后在调用 Liquibase 重建架构之前将其设置为默认值,如下所示:

    ...
    connection = DriverManager.getConnection(...)

    connection.createStatement().executeUpdate("create schema $schemaName")

    connection.schema = schemaName.toUpperCase()

    // invoke Liquibase with this connection
    ...

尽管打开了与 H2 的不区分大小写的连接,toUpperCase() 调用仍然被证明是必要的。不知道为什么...

  • jOOQ 引用所有模式对象的名称,以使它们不区分大小写。然而,据我了解,引号用于在 H2 中强制区分大小写。因此,生成的查询中存在引号会由于无法找到对象而导致大量错误。解决办法是向查询生成器提供不同的 RenderNameStyle 来省略引号,例如:

    ...
    val settings = Settings().withRenderNameStyle(RenderNameStyle.AS_IS)

    val dslContext = DSL.using(connection, SQLDialect.H2, settings)
    ...
  • 希望这对其他人有帮助。

    关于java - 单元测试中的 jOOQ + Liquibase + H2 结果出现 "schema not found"异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48811539/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com