Связанные со схемой проблемы с Flyway / Spring и встроенной базой данных H2
Я создаю приложение Spring 3 MVC, которое использует базу данных MySQL и недавно интегрировало Flyway в решение для управления миграциями базы данных. Я успешно настроил свой applicationContext.XML в соответствии с Flyway документация такой, что при запуске приложения Flyway будет мигрировать до последней версии.
у меня возникли проблемы с получением Flyway, чтобы хорошо играть с моими модульными / функциональными тестами. Я использую Spring Data JPA для доступа к данным layer и построили некоторые тесты JUnit для тестирования некоторых пользовательских запросов.
конфигурация приложения, которую я использую для этих тестов:
<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>
когда я запускаю модульные тесты (либо через 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.access0(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
Я не могу понять, как заставить базу данных H2 распознать тот факт, что я хочу использовать схему под названием medical_claims_tracker. Я использовал ответ, чтобы помочь мне попробовать различные URL-адреса подключения и ответ чтобы помочь мне прибить переопределения applicationContext для использования во время тестирования.
Я подозреваю, что это связано с тем, что H2 отбрасывает схему после первоначального создания, но до запуска теста, но я думал, что DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;
решил бы это для меня. Интересно, что если я удалю спецификацию схемы в конфигурации Flyway bean:
<bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate">
<property name="dataSource" ref="dataSource"/>
<property name="sqlMigrationPrefix" value="Migration_"/>
</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.access0(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
так кажется, что с первым конфигурация, Flyway может создать таблицу schema_version в схеме medical_claims_tracker, но не может найти эту схему для запуска тестов, тогда как во второй версии он даже не может найти схему "по умолчанию", в которой создать таблицу schema_version. Это правильно,или я неправильно понял?
6 ответов
имя схемы в сценарии инициализации должно быть указано или то, которое вы передаете Flyway, помещено в верхний регистр.
из того, что я тестировал, вся проблема возникает только при смешивании flyway и H2 с режимом совместимости MySql (не происходит, если режим MySql). Это вызвано несоответствием чувствительности к регистру:
- h2 во время инициализации создает схему по умолчанию "PUBLIC" (верхний регистр!)
- когда flyway пытается получить имя схемы по умолчанию, он получает "public" (нижний регистр!)
- когда flyway пытается изменить текущую схему на "public" (нижний регистр!) ошибка заброшенный. Даже при установке схем flyway в "MYSCHEMA", в какой-то момент процесса миграции он всегда пытается изменить на "public".
в моем текущем приложении мы используем MySql в качестве основной базы данных и H2 для тестирования. Мое обходное решение включает создание "public" (нижний регистр!) схема во время инициализации h2:
конфигурация источника данных spring:
<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>
init_tests.в SQL:
CREATE SCHEMA IF NOT EXISTS "public";
не красиво, но работает - надеюсь, что помогает!
от http://www.h2database.com/javadoc/org/h2/engine/DbSettings.html:
databaseToUpper: Настройка базы данных DATABASE_TO_UPPER (по умолчанию: true).
короткие имена базы данных преобразуются в верхний регистр для базы данных() функция... установка этого значения в "false" является экспериментальной. Если установлено значение false, все имена идентификаторов (имена таблиц, имена столбцов) чувствительны к регистру...
в проблема в том, что по умолчанию имена схем находятся в верхнем регистре.
устранение:
добавить ;DATABASE_TO_UPPER=false
к url базы данных
проблема в том, что идентификатор public
в заявлении есть нижний регистр и цитировать:
CREATE TABLE "public"...(...)
это должно быть либо без кавычек:
CREATE TABLE public...(...)
или верхний регистр:
CREATE TABLE "PUBLIC"...(...)
причина, по которой H2 возвращает нижний регистр "public" в метаданных базы данных, заключается в том, что режим MySQL используется в URL базы данных (;MODE=MySQL
). Так что не использование режима MySQL может решить проблему.
у меня была аналогичная проблема, хотя я не использую Spring. Я добавляю H2 в память DB для тестов поверх существующей установки с jOOQ + Flyway + PostgreSQL.
решение для меня было комбинацией изменений:
- из ответа @Omid выше добавьте
;DATABASE_TO_UPPER=false
к URL запуска - из ответа @Tom добавьте создание схемы в сценарий init SQL:
CREATE SCHEMA IF NOT EXISTS public;
(мне не нужно было использовать backticks). - наконец, в том же скрипте добавьте 2-я строка
SET SCHEMA public;
после создания схемы.
обратите внимание, что я не смог добавить ;SCHEMA=public
к URL-адресу init, потому что это вызывало ошибку до создания схемы. Как вариант:
- добавить
;DATABASE_TO_UPPER=false;INIT=CREATE SCHEMA IF NOT EXISTS public;
к URL запуска. - затем добавить
SET SCHEMA public;
к вашему сценарию SQL init.
на всякий случай, если вы хотите попробовать liquibase.
Я использую MySQL в качестве среды prod и h2 в качестве тестовой среды.
генерировать коды jooq с: gradle + liquibase + h2
найдено это может решить проблему:
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"))
));
напишите профиль, чтобы применить это весной для h2. Так что MySQL configs все еще в порядке.
последние документы здесь jooq-3.9: настройки-название-стиль.