Flyway/Spring 和 H2 嵌入式数据库的 Schema 相关问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14972408/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:44:42  来源:igfitidea点击:

Schema related problems with Flyway / Spring and H2 embedded database

springh2flyway

提问by stevenghines

I am building a Spring 3 MVC app that uses a MySQL database and have recently integrated Flyway into the solution to manage the database migrations. I have successfully configured my applicationContext.xml according to the Flyway documentationsuch that, upon application startup, Flyway will migrate to the latest version.

我正在构建一个使用 MySQL 数据库的 Spring 3 MVC 应用程序,并且最近将 Flyway 集成到解决方案中以管理数据库迁移。我已经根据Flyway 文档成功配置了我的 applicationContext.xml,这样在应用程序启动时,Flyway 将迁移到最新版本。

I am having trouble getting Flyway to play nicely with my unit / functional tests. I am using Spring Data JPA for my data access layer and have built some JUnit tests to test some custom queries.

我无法让 Flyway 很好地与我的单元/功能测试一起玩。我将 Spring Data JPA 用于我的数据访问层,并构建了一些 JUnit 测试来测试一些自定义查询。

The application config I use for these tests is:

我用于这些测试的应用程序配置是:

<jdbc:embedded-database id="dataSource" type="H2" />

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
  <property name="driverClassName" value="org.h2.Driver"/>
  <property name="url" value="jdbc:h2:mem:medical_claims_tracker;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;MODE=MySQL;INIT=CREATE SCHEMA IF NOT EXISTS medical_claims_tracker" />
</bean>

<bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate">
    <property name="dataSource" ref="dataSource"/>
    <property name="schemas" value="medical_claims_tracker"/>
    <property name="sqlMigrationPrefix" value="Migration_"/>
</bean>

When I run my unit tests (either through Eclipse or using Maven) I get the following exception:

当我运行我的单元测试(通过 Eclipse 或使用 Maven)时,我收到以下异常:

ERROR: org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@4cd4544] to prepare test instance [name.hines.steven.medical_claims_tracker.repositories.ExpenseRepositoryTest@1664a9b]
java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157)
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:103)
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:73)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:313)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access
<bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate">
    <property name="dataSource" ref="dataSource"/>
    <property name="sqlMigrationPrefix" value="Migration_"/>
</bean>
0(ParentRunner.java:42) at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:184) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flyway' defined in class path resource [tests_persistence-applicationContext.xml]: Invocation of init method failed; nested exception is com.googlecode.flyway.core.api.FlywayException: Error setting current schema to medical_claims_tracker at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:532) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:295) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198) at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:741) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:106) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:57) at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100) at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:248) at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124) at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148) ... 24 more Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flyway' defined in class path resource [tests_persistence-applicationContext.xml]: Invocation of init method failed; nested exception is com.googlecode.flyway.core.api.FlywayException: Error setting current schema to medical_claims_tracker at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1486) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:295) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:285) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198) at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:439) at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:277) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:139) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.<init>(PersistenceExceptionTranslationInterceptor.java:79) at org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisor.<init>(PersistenceExceptionTranslationAdvisor.java:71) at org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor.setBeanFactory(PersistenceExceptionTranslationPostProcessor.java:85) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1506) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1474) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524) ... 37 more Caused by: com.googlecode.flyway.core.api.FlywayException: Error setting current schema to medical_claims_tracker at com.googlecode.flyway.core.Flyway.execute(Flyway.java:1250) at com.googlecode.flyway.core.Flyway.migrate(Flyway.java:820) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1612) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1553) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1483) ... 54 more Caused by: org.h2.jdbc.JdbcSQLException: Schema "medical_claims_tracker" not found; SQL statement: SET SCHEMA "medical_claims_tracker" [90079-160] at org.h2.message.DbException.getJdbcSQLException(DbException.java:329) at org.h2.message.DbException.get(DbException.java:169) at org.h2.message.DbException.get(DbException.java:146) at org.h2.engine.Database.getSchema(Database.java:1501) at org.h2.command.dml.Set.update(Set.java:290) at org.h2.command.CommandContainer.update(CommandContainer.java:73) at org.h2.command.Command.executeUpdate(Command.java:219) at org.h2.jdbc.JdbcPreparedStatement.execute(JdbcPreparedStatement.java:181) at com.googlecode.flyway.core.dbsupport.JdbcTemplate.execute(JdbcTemplate.java:280) at com.googlecode.flyway.core.dbsupport.h2.H2DbSupport.setCurrentSchema(H2DbSupport.java:79) at com.googlecode.flyway.core.Flyway.execute(Flyway.java:1247) ... 62 more

I can't work out how to get the H2 database to recognise the fact that I want to use a schema called medical_claims_tracker. I used this answerto help me try out different connection URLs and this answerto help me nail down the applicationContext overrides for use during testing.

我不知道如何让 H2 数据库识别出我想使用名为medical_claims_tracker 的模式这一事实。我使用这个答案来帮助我尝试不同的连接 URL,这个答案帮助我确定在测试期间使用的 applicationContext 覆盖。

I suspect it is something to do with H2 dropping the schema after initial creation but before the test can be run, but I thought that DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;would solve that for me. Interestingly, if I remove the specification of the schema in the flyway bean config:

我怀疑这与 H2 在初始创建之后但在测试可以运行之前删除架构有关,但我认为这DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;可以为我解决这个问题。有趣的是,如果我删除 flyway bean 配置中的模式规范:

INFO : com.googlecode.flyway.core.metadatatable.MetaDataTableImpl - Creating Metadata table: "public"."schema_version"
ERROR: org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@4bd27069] to prepare test instance [name.hines.steven.medical_claims_tracker.repositories.ExpenseRepositoryTest@64d22462]
java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157)
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:103)
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:73)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:313)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
 <property name="driverClassName" value="org.h2.Driver"/>
 <property name="url" value="jdbc:h2:mem:MY_APP;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;INIT=RUNSCRIPT FROM 'classpath:db/migration/test/init_tests.sql';"/>
 <property name="username" value="sa"/>
 <property name="password" value=""/>
</bean>
0(ParentRunner.java:42) at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:184) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flyway' defined in class path resource [tests_persistence-applicationContext.xml]: Invocation of init method failed; nested exception is com.googlecode.flyway.core.api.FlywayException: Error executing statement at line 17: CREATE TABLE "public"."schema_version" ( "version_rank" INT NOT NULL, "installed_rank" INT NOT NULL, "version" VARCHAR(50) NOT NULL, "description" VARCHAR(200) NOT NULL, "type" VARCHAR(20) NOT NULL, "script" VARCHAR(1000) NOT NULL, "checksum" INT, "installed_by" VARCHAR(30) NOT NULL, "installed_on" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "execution_time" INT NOT NULL, "success" BOOLEAN NOT NULL ) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:532) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:295) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198) at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:741) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:106) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:57) at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100) at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:248) at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124) at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148) ... 24 more Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flyway' defined in class path resource [tests_persistence-applicationContext.xml]: Invocation of init method failed; nested exception is com.googlecode.flyway.core.api.FlywayException: Error executing statement at line 17: CREATE TABLE "public"."schema_version" ( "version_rank" INT NOT NULL, "installed_rank" INT NOT NULL, "version" VARCHAR(50) NOT NULL, "description" VARCHAR(200) NOT NULL, "type" VARCHAR(20) NOT NULL, "script" VARCHAR(1000) NOT NULL, "checksum" INT, "installed_by" VARCHAR(30) NOT NULL, "installed_on" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "execution_time" INT NOT NULL, "success" BOOLEAN NOT NULL ) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1486) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:295) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:285) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198) at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:439) at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:277) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:139) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.<init>(PersistenceExceptionTranslationInterceptor.java:79) at org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisor.<init>(PersistenceExceptionTranslationAdvisor.java:71) at org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor.setBeanFactory(PersistenceExceptionTranslationPostProcessor.java:85) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1506) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1474) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524) ... 37 more Caused by: com.googlecode.flyway.core.api.FlywayException: Error executing statement at line 17: CREATE TABLE "public"."schema_version" ( "version_rank" INT NOT NULL, "installed_rank" INT NOT NULL, "version" VARCHAR(50) NOT NULL, "description" VARCHAR(200) NOT NULL, "type" VARCHAR(20) NOT NULL, "script" VARCHAR(1000) NOT NULL, "checksum" INT, "installed_by" VARCHAR(30) NOT NULL, "installed_on" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "execution_time" INT NOT NULL, "success" BOOLEAN NOT NULL ) at com.googlecode.flyway.core.dbsupport.SqlStatement.execute(SqlStatement.java:78) at com.googlecode.flyway.core.dbsupport.SqlScript.execute(SqlScript.java:94) at com.googlecode.flyway.core.metadatatable.MetaDataTableImpl.doInTransaction(MetaDataTableImpl.java:124) at com.googlecode.flyway.core.metadatatable.MetaDataTableImpl.doInTransaction(MetaDataTableImpl.java:121) at com.googlecode.flyway.core.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:54) at com.googlecode.flyway.core.metadatatable.MetaDataTableImpl.create(MetaDataTableImpl.java:121) at com.googlecode.flyway.core.metadatatable.MetaDataTableImpl.createIfNotExists(MetaDataTableImpl.java:134) at com.googlecode.flyway.core.Flyway.execute(Flyway.java:834) at com.googlecode.flyway.core.Flyway.execute(Flyway.java:820) at com.googlecode.flyway.core.Flyway.execute(Flyway.java:1259) at com.googlecode.flyway.core.Flyway.migrate(Flyway.java:820) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1612) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1553) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1483) ... 54 more Caused by: org.h2.jdbc.JdbcSQLException: Schema "public" not found; SQL statement: CREATE TABLE "public"."schema_version" ( "version_rank" INT NOT NULL, "installed_rank" INT NOT NULL, "version" VARCHAR(50) NOT NULL, "description" VARCHAR(200) NOT NULL, "type" VARCHAR(20) NOT NULL, "script" VARCHAR(1000) NOT NULL, "checksum" INT, "installed_by" VARCHAR(30) NOT NULL, "installed_on" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "execution_time" INT NOT NULL, "success" BOOLEAN NOT NULL ) [90079-160] at org.h2.message.DbException.getJdbcSQLException(DbException.java:329) at org.h2.message.DbException.get(DbException.java:169) at org.h2.message.DbException.get(DbException.java:146) at org.h2.command.Parser.getSchema(Parser.java:613) at org.h2.command.Parser.getSchema(Parser.java:620) at org.h2.command.Parser.parseCreateTable(Parser.java:5147) at org.h2.command.Parser.parseCreate(Parser.java:3800) at org.h2.command.Parser.parsePrepared(Parser.java:324) at org.h2.command.Parser.parse(Parser.java:279) at org.h2.command.Parser.parse(Parser.java:251) at org.h2.command.Parser.prepareCommand(Parser.java:217) at org.h2.engine.Session.prepareLocal(Session.java:415) at org.h2.engine.Session.prepareCommand(Session.java:364) at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1119) at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:164) at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:152) at com.googlecode.flyway.core.dbsupport.JdbcTemplate.executeStatement(JdbcTemplate.java:296) at com.googlecode.flyway.core.dbsupport.SqlStatement.execute(SqlStatement.java:76) ... 71 more

I get a different exception:

我得到一个不同的例外:

CREATE SCHEMA IF NOT EXISTS "public";

So it seems that with the first configuration, Flyway is able to create the schema_version table in the medical_claims_tracker schema but can't then find that schema to run the tests in, whereas in the second version, it can't even find the "default" schema in which to create the schema_version table. Is this correct, or have I got this the wrong way round?

因此,似乎在第一个配置中,Flyway 能够在 medical_claims_tracker 模式中创建 schema_version 表,但无法找到该模式来运行测试,而在第二个版本中,它甚至找不到“默认” " 在其中创建 schema_version 表的架构。这是正确的,还是我弄错了?

采纳答案by Axel Fontaine

The schema name in the init script should be quoted or the one you pass to Flyway put in uppercase.

init 脚本中的模式名称应该被引用,或者你传递给 Flyway 的名称是大写的。

回答by Omid

From http://www.h2database.com/javadoc/org/h2/engine/DbSettings.html:

http://www.h2database.com/javadoc/org/h2/engine/DbSettings.html

databaseToUpper: Database setting DATABASE_TO_UPPER (default: true).

Database short names are converted to uppercasefor the DATABASE() function ... Setting this to "false" is experimental. When set to false, all identifier names (table names, column names) are case sensitive...

databaseToUpper:数据库设置 DATABASE_TO_UPPER(默认值:true)。

对于 DATABASE() 函数,数据库短名称被转换为大写...... 将其设置为“false”是实验性的。当设置为 false 时,所有标识符名称(表名、列名)都区分大小写...

the problem is that by default schema names are in UPPERCASE.

问题是默认模式名称是大写的。

Solution:

解决方案:

add ;DATABASE_TO_UPPER=falseto database url

添加;DATABASE_TO_UPPER=false到数据库网址

回答by Tom

From what I've tested the whole problem occurs only while mixing flyway and H2 with MySql compatibility mode on (doesn't occur if MySql mode is of). It is caused by case sensitivity inconsistency:

从我测试的情况来看,只有在将 flyway 和 H2 与 MySql 兼容模式混合时才会出现整个问题(如果 MySql 模式是,则不会发生)。它是由大小写不一致引起的:

  1. h2 during initialization creates default schema 'PUBLIC' (uppercase!)
  2. when flyway tries to get default schema name it gets 'public' (lowercase!)
  3. when flyway tries to change current schema to 'public' (lowercase!) error is thrown. Even when setting flyway schemas to 'MYSCHEMA', at some point of it migration process it always tries to change to 'public'.
  1. 初始化期间的 h2 创建默认架构“PUBLIC”(大写!)
  2. 当 flyway 尝试获取默认模式名称时,它会变为“public”(小写!)
  3. 当 flyway 尝试将当前架构更改为“public”(小写!)时会引发错误。即使将飞行模式设置为“MYSCHEMA”,在迁移过程的某个时刻,它也总是尝试更改为“公共”。

In my currently developed application we use MySql as a main database and H2 for testing. My workaround involves creating 'public' (lowercase!) schema during h2 initialization:

在我目前开发的应用程序中,我们使用 MySql 作为主数据库和 H2 进行测试。我的解决方法涉及在 h2 初始化期间创建“公共”(小写!)架构:

spring datasource configuration:

spring数据源配置:

CREATE TABLE "public"...(...)

init_tests.sql:

init_tests.sql:

CREATE TABLE public...(...)

Isn't beautifull but works - hope that helps!

不漂亮但有效 - 希望有帮助!

回答by Thomas Mueller

The problem is that the identifier publicin the statement is lower case andquoted:

问题是public语句中的标识符是小写的引用了:

CREATE TABLE "PUBLIC"...(...)

It should be either unquoted:

它应该不加引号:

DefaultConfiguration jooqConfiguration = new DefaultConfiguration();
jooqConfiguration.set(new Settings()
        // make everything to uppercase 
        .withRenderNameStyle(RenderNameStyle.UPPER)
        // mapping oldSchemaName to newSchemaName
        .withRenderMapping(new RenderMapping().withSchemata(
                new MappedSchema()
                        .withInput("input_schema")
                        .withOutput("OUTPUT_SCHEMA"))
        ));

or uppercase:

或大写:

##代码##

The reason why H2 returns the lowercase "public" in the database meta data is that the MySQL mode is used in the database URL (;MODE=MySQL). So notusing the MySQL mode might solve the problem.

H2之所以在数据库元数据中返回小写的“public”,是因为数据库URL(;MODE=MySQL)中使用了MySQL模式。所以使用 MySQL 模式可能会解决问题。

回答by Rónán ó Braonáin

I had a similar issue, although I'm not using Spring. I'm adding H2 in-memory DB for tests on top of an existing setup with jOOQ + Flyway + PostgreSQL.

我有一个类似的问题,虽然我没有使用 Spring。我正在使用 jOOQ + Flyway + PostgreSQL 在现有设置之上添加 H2 内存数据库以进行测试。

The solution for me was a combination of changes:

对我来说,解决方案是多种变化的组合:

  1. From @Omid's answer above, add ;DATABASE_TO_UPPER=falseto the startup URL
  2. From @Tom's answer, add the schema creation to an init SQL script: CREATE SCHEMA IF NOT EXISTS public;(I didn't need to use the backticks).
  3. Finally in the same script, add a 2nd line of SET SCHEMA public;after schema creation.
  1. 从上面@Omid 的回答中,添加;DATABASE_TO_UPPER=false到启动 URL
  2. 根据@Tom 的回答,将模式创建添加到 init SQL 脚本中:(CREATE SCHEMA IF NOT EXISTS public;我不需要使用反引号)。
  3. 最后在同一个脚本中,SET SCHEMA public;在模式创建之后添加第二行。

Note that I wasn't able to add ;SCHEMA=publicto the init URL, because this was throwing an error before the schema was being created. Alternatively:

请注意,我无法添加;SCHEMA=public到 init URL,因为这会在创建架构之前引发错误。或者:

  1. Add ;DATABASE_TO_UPPER=false;INIT=CREATE SCHEMA IF NOT EXISTS public;to the startup URL.
  2. Then add SET SCHEMA public;to your init SQL script.
  1. 添加;DATABASE_TO_UPPER=false;INIT=CREATE SCHEMA IF NOT EXISTS public;到启动 URL。
  2. 然后添加SET SCHEMA public;到您的 init SQL 脚本中。

回答by Daniel Wei

Just in case if you want to try liquibase.

以防万一,如果您想尝试liquibase

I'm using MySQL as my prod environment and h2 as my test environment.

我使用 MySQL 作为我的生产环境和 h2 作为我的测试环境。

Generate jooq codes with: gradle + liquibase + h2

使用以下命令生成 jooq 代码: gradle + liquibase + h2

Found this can solve the problem:

发现这样可以解决问题:

##代码##

Write a profile to apply this in spring for h2. So that mysql configs still fine.

编写配置文件以在春季为 h2 应用此功能。所以mysql配置仍然很好。

Latest docs here jooq-3.9: settings-name-style.

最新文档jooq-3.9: settings-name-style