Java Hibernate, Liquibase supports cross databases and SQLite? - java

I'm using Spring Boot 1.5.2 with Hibernate 5 and try to support as many databases as possible (i.e: Hibernate will create all the tables in SQLite 3, then I use Liquibase as an abstract layer to generate the XML change-log files for all kind of supported databases which Liquibase claimed: supported databases).
so I added the dependency for Liquibase in pom.xml (Maven).
<!-- Database schema versions migration -->
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
</dependency>
and a plugin to generate the changelog XML file from created database of Hibernate
<!-- Database schema versions migration -->
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.5.3</version>
<configuration>
<propertyFile>src/main/resources/liquibase.properties</propertyFile>
</configuration>
</plugin>
I have some configuration in liquibase.properties to connect to SQLite3 datab file, then I can run this command to create a changelog file.
mvn liquibase:generateChangeLog
The output changelog I cannot recreate in another different SQLite 3 db file, due to the addPrimaryKey element:
<changeSet author="rasdaman (generated)" id="1497363976895-86">
<addPrimaryKey columnNames="address_id" tableName="address"/>
</changeSet>
and the error in Java Spring Boot when it starts:
addPrimaryKey is not supported on sqlite,
classpath:/database_versions/db.changelog-master.xml::1497366115846-62::rasdaman (generated)
at liquibase.changelog.DatabaseChangeLog.validate(DatabaseChangeLog.java:266)
at liquibase.Liquibase.update(Liquibase.java:210)
at liquibase.Liquibase.update(Liquibase.java:192)
at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:431)
at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:388)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
If I use the generated output file from SQLite by Liquibase and allow Spring Boot to starts with Postgresql datasource, I got another error:
org.springframework.beans.factory.BeanCreationException: Error creating
bean with name 'liquibase' defined in class path resource
[org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: Invocation of init method failed; nested exception is liquibase.exception.MigrationFailedException: Migration failed for change set classpath:/database_versions/db.changelog-master.xml::1497366115846-1:: (generated):
Reason: liquibase.exception.DatabaseException: ERROR: syntax error at or near "("
Position: 72 [Failed SQL: CREATE TABLE public."HT_abstract_coverage" (abstract_coverage_id BIGINT(2000000000, 10) NOT NULL, hib_sess_id CHAR(36))]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628)
So it seems I don't have another tool to generate an abstract data file like XML automatically which can be imported to any common databases without problems? If you have any suggestion, please advise!
Thanks,

The problem is Liquibase does not support SQLite very well http://www.liquibase.org/documentation/changes/add_primary_key.html , also Hibernate which needs a third party SQLite dialect and the performance for write is not good, so I think Liquibase could work well with another databases like: postgresql, mysql, hyperSQL,...

Related

Flyway is unable to create and find database in Spring Boot [duplicate]

Question: Is it possible to create a new DB in a migration script and then connect to it? How?
My Scenario:
I'm trying to use flyway in my Java project (RESTful application using Jersey2.4 + tomcat 7 + PostgreSQL 9.3.1 + EclipseLink) for managing the changes between different developers which are using git. I wrote my init script and ran it with:
PGPASSWORD='123456' psql -U postgres -f migration/V1__initDB.sql
and it worked fine. The problem is that I can't create new DB with my scripts. when I include the following line in my script:
CREATE DATABASE my_database OWNER postgres ENCODING 'UTF8';
I get this error:
org.postgresql.util.PSQLException: ERROR: CREATE DATABASE cannot run inside a transaction block
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2157)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1886)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:555)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:403)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:395)
at com.googlecode.flyway.core.dbsupport.JdbcTemplate.executeStatement(JdbcTemplate.java:230)
at com.googlecode.flyway.core.dbsupport.SqlScript.execute(SqlScript.java:89)
at com.googlecode.flyway.core.resolver.sql.SqlMigrationExecutor.execute(SqlMigrationExecutor.java:72)
at com.googlecode.flyway.core.command.DbMigrate$2.doInTransaction(DbMigrate.java:252)
at com.googlecode.flyway.core.command.DbMigrate$2.doInTransaction(DbMigrate.java:250)
at com.googlecode.flyway.core.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:56)
at com.googlecode.flyway.core.command.DbMigrate.applyMigration(DbMigrate.java:250)
at com.googlecode.flyway.core.command.DbMigrate.access$700(DbMigrate.java:47)
at com.googlecode.flyway.core.command.DbMigrate$1.doInTransaction(DbMigrate.java:189)
at com.googlecode.flyway.core.command.DbMigrate$1.doInTransaction(DbMigrate.java:138)
at com.googlecode.flyway.core.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:56)
at com.googlecode.flyway.core.command.DbMigrate.migrate(DbMigrate.java:137)
at com.googlecode.flyway.core.Flyway$1.execute(Flyway.java:872)
at com.googlecode.flyway.core.Flyway$1.execute(Flyway.java:819)
at com.googlecode.flyway.core.Flyway.execute(Flyway.java:1200)
at com.googlecode.flyway.core.Flyway.migrate(Flyway.java:819)
at ir.chom.MyApp.<init>(MyApp.java:28)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.glassfish.hk2.utilities.reflection.ReflectionHelper.makeMe(ReflectionHelper.java:1117)
at org.jvnet.hk2.internal.Utilities.justCreate(Utilities.java:867)
at org.jvnet.hk2.internal.ServiceLocatorImpl.create(ServiceLocatorImpl.java:814)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:906)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:898)
at org.glassfish.jersey.server.ApplicationHandler.createApplication(ApplicationHandler.java:300)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:279)
at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:302)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:167)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:349)
at javax.servlet.GenericServlet.init(GenericServlet.java:160)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1280)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1091)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5176)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5460)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3954)
at org.apache.catalina.loader.WebappLoader.backgroundProcess(WebappLoader.java:426)
at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1345)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1530)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1519)
at java.lang.Thread.run(Thread.java:724)
It seems that this is a problem with JDBC that uses autocommit option. This option can be disabled with something like this:
Connection connection = dataSource.getConnection();
Connection.setAutoCommit(false); // Disables auto-commit.
but I don't know how to pass this option to flyway connection. Also if I solve this I think I will have problem with passing password to \c command.
Flyway always operates within the database used in the jdbc connection string.
Once connected, all scripts run within a transaction. As CREATE DATABASE is not supported within transactions, you will not be able to accomplish what you want.
What you can do however, is create a schema instead. Flyway will even do this for you, if you point it at a non-existing one.
I dont know if this is even possible to do in flyway.
Flyway is intended to connect to an already existing database (whether it is empty or not). It also would be a good practice to keep your database creation separate from your database migrations.
Here is a workaround that worked for me (assuming the use of the Maven plugin):
Configure the plugin with two executions. The first execution creates the database. The second execution migrates an existing database.
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>${flyway.version}</version>
<executions>
<execution>
<id>create-db</id>
<goals>
<goal>migrate</goal>
</goals>
<configuration>
<driver>org.postgresql.Driver</driver>
<url>jdbc:postgresql://database-server/</url>
<user>postgres</user>
<password>password</password>
<placeholders>
<DATABASE.NAME>MyDatabase</DATABASE.NAME>
</placeholders>
<locations>
<location>com/foo/bar/database/create</location>
</locations>
</configuration>
</execution>
<execution>
<id>migrate-db</id>
<goals>
<goal>migrate</goal>
</goals>
<configuration>
<driver>org.postgresql.Driver</driver>
<url>jdbc:postgresql://database-server/MyDatabase</url>
<user>postgres</user>
<password>password</password>
<locations>
<location>com/foo/bar/database/migrate</location>
</locations>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
</dependencies>
</plugin>
Then add V1__Created_database.sql to the com/foo/bar/database/create directory. This file contains:
CREATE DATABASE ${DATABASE.NAME}
Flyway can't create database for you.
It can create schema if you didn't create one by
flyway.schemas: schema1,schema2
You can try what is suggested in this issue: https://github.com/flyway/flyway/issues/2556, use the createDatabaseIfNotExist parameter in the mysql url configured in flyway, as below:
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>6.4.1</version>
<configuration>
<url>jdbc:mysql://localhost:3306/<databaseName>?createDatabaseIfNotExist=true</url>
<user>root</user>
<password>root</password>
</configuration>
If u have schema database creation command in V1 of your scripts, flyway can generate it but not database:
flyway -baselineOnMigrate=true -url=jdbc:mysql://localhost/ -schemas=test_db -user=root -password=root_pass -locations=filesystem:/path/to/scrips/ migrate
and similar to this in the script file:
DROP SCHEMA IF EXISTS `test_db` ;
CREATE SCHEMA `test_db` COLLATE utf8_general_ci ;

Cannot determine embedded database driver class for database type NONE with Redis in Spring Boot

I use Spring Boot and redis. I added in pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
And created class RedisConfig, which contains Beans JedisConnectionFactory jedisConnectionFactory and RedisTemplate< String, Object > redisTemplate().
When I run application, I get error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Cannot determine embedded database driver class for database type NONE
Action:
If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
I don't use a embeded redis. Redis work on my computer on localhost.
application.properties:
spring.redis.host=localhost
spring.redis.port=6379
Why there is this error?
There is a couple of issues:
spring-boot-starter-redis is deprecated. Use spring-boot-starter-data-redis instead.
Remove the spring-boot-starter-data-jpa dependency. Spring Data Redis does not support JPA and it's not needed. This is actually causing your error.

JPA Entities showing as not enhanced when referenced from another JAR

I have a Maven Java project with a JAR containing my business logic and JPA persistence entities. Those entities are enhanced by a Maven plug-in at build time. I also have another project which has a dependency on that JAR. i.e.
EAR
|->JAR - with entities and persistence.xml
|->WAR - dependent on JAR above
When I access the entities from within the JAR everything works fine. However if I try and access the entities from the WAR file I get this error:
11:55:07,916 ERROR [org.jboss.as.ejb3.invocation] (default task-4) JBAS014134:
EJB Invocation failed on component PersonResource for method
public za.co.shared.PersonDTO za.co.ws.PersonResource.get(java.lang.Long):
javax.ejb.EJBException: <openjpa-2.3.0-r422266:1540826 nonfatal user error>
org.apache.openjpa.persistence.ArgumentException: This configuration disallows
runtime optimization, but the following listed types were not enhanced at
build time or at class load time with a javaagent:
... long list of all my entities
The type "class za.co.entities.Person" has not been enhanced.
Which doesn't make sense to me because the classes are definitely enhanced at build time.
My POM for the JAR project contains:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>openjpa-maven-plugin</artifactId>
<version>1.2</version>
<configuration>
<includes>za.co.entities.Person</includes>
<enforcePropertyRestrictions>true</enforcePropertyRestrictions>
</configuration>
<executions>
<execution>
<id>JPA Enhance</id>
<phase>process-classes</phase>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa</artifactId>
<version>2.2.2</version>
</dependency>
</dependencies>
</plugin>
Can the JPA entities be referenced from a different library?
Edit
I've decompiled the WAR file and the JAR that is referenced within it and I can see that the classes are in fact enhanced. So clearly it's not a problem with the way that is working. Could be some sort of configuration problem?
I moved all my JPA entities into their own JAR file and referenced that from my EJB modules and from the WAR. i.e.
EAR
|->JAR - JPA entities only and pesistence.xml
|->JAR - business logic in EJBs (including EntityManager calls to retrieve data)
| dependent on JAR above.
|->WAR - dependent on the first JAR only
In this way the code in the WAR file can access the JPA entities in the first JAR. However if I add the second JAR as a dependency in the WAR file and try and access the entity manager calls then the original error returns. Also lazy loading on the JPA entities is disabled in the WAR.

java.lang.NoSuchMethodError using JOOQ

I was trying to use JOOQ in glassfish. I used code generator like this:
java -cp jOOQ-lib/jooq-3.3.1.jar:jOOQ-lib/jooq-meta-3.3.1.jar:jOOQ-lib/jooq-codegen-3.3.1.jar:mysql-connector-java-5.1.29-bin.jar:. org.jooq.util.GenerationTool /db.xml
Then imported the generated folder to my project.(I'm not using jooq maven plugin). When I deploy web app in glassfish I see this in server.log
[#|2014-04-06T14:53:37.720+0430|SEVERE|glassfish3.1.2|com.sun.xml.ws.server.sei.TieHandler|_ThreadID=670;_ThreadName=Thread-2;|org.jooq.impl.TableImpl.<init>(Ljava/lang/String;Lorg/jooq/Schema;Lorg/jooq/Table;[Lorg/jooq/Field;Ljava/lang/String;)V
java.lang.NoSuchMethodError: org.jooq.impl.TableImpl.<init>(Ljava/lang/String;Lorg/jooq/Schema;Lorg/jooq/Table;[Lorg/jooq/Field;Ljava/lang/String;)V
I have not changed any maven config just netbeans default config. maven artifact:
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq</artifactId>
<version>3.3.1</version>
</dependency>
my db.xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration>
<!-- Configure the database connection here -->
<jdbc>
<driver>com.mysql.jdbc.Driver</driver>
<url>jdbc:mysql://127.0.0.1/bulkdb?useUnicode=true</url>
<user>user</user>
<password>pass</password>
</jdbc>
<generator>
<database>
<name>org.jooq.util.mysql.MySQLDatabase</name>
<inputSchema>bulkdb</inputSchema>
<includes>.*</includes>
<excludes></excludes>
</database>
<target>
<packageName>bulkdb</packageName>
<directory>/home/user/jooq</directory>
</target>
</generator>
</configuration>
What is going wrong? Can someone help?
[UPDATE]
Actually there is two version of JOOQ in app server class path: one in lib directory of the domain(domain1/lib/) with version 3.1 and second one is 3.3.1 that is bundled in war file. Does this cause problems?
Actually there is two version of JOOQ in app server class path: one in lib directory of the domain(domain1/lib/) with version 3.1 and second one is 3.3.1 that is bundled in war file. Does this cause problems?
Yes, of course :-)
If you want to use both versions in parallel (do you really?), then you will probably need to resort to something like OSGi to be able to load the same class names in separate class loaders.
In your case, jOOQ 3.1 is loaded first by your application server, and thus jOOQ 3.3 cannot be loaded fully any more. The code generated with jOOQ 3.3 operates on new internal methods in TableImpl, which have been added in jOOQ 3.2 or 3.3, but since you're loading jOOQ 3.1, those methods aren't there. Note that this can happen with any external dependencies.
The solution here is really to remove jOOQ 3.1 from your application server.

How to create a database with flyway?

Question: Is it possible to create a new DB in a migration script and then connect to it? How?
My Scenario:
I'm trying to use flyway in my Java project (RESTful application using Jersey2.4 + tomcat 7 + PostgreSQL 9.3.1 + EclipseLink) for managing the changes between different developers which are using git. I wrote my init script and ran it with:
PGPASSWORD='123456' psql -U postgres -f migration/V1__initDB.sql
and it worked fine. The problem is that I can't create new DB with my scripts. when I include the following line in my script:
CREATE DATABASE my_database OWNER postgres ENCODING 'UTF8';
I get this error:
org.postgresql.util.PSQLException: ERROR: CREATE DATABASE cannot run inside a transaction block
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2157)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1886)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:555)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:403)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:395)
at com.googlecode.flyway.core.dbsupport.JdbcTemplate.executeStatement(JdbcTemplate.java:230)
at com.googlecode.flyway.core.dbsupport.SqlScript.execute(SqlScript.java:89)
at com.googlecode.flyway.core.resolver.sql.SqlMigrationExecutor.execute(SqlMigrationExecutor.java:72)
at com.googlecode.flyway.core.command.DbMigrate$2.doInTransaction(DbMigrate.java:252)
at com.googlecode.flyway.core.command.DbMigrate$2.doInTransaction(DbMigrate.java:250)
at com.googlecode.flyway.core.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:56)
at com.googlecode.flyway.core.command.DbMigrate.applyMigration(DbMigrate.java:250)
at com.googlecode.flyway.core.command.DbMigrate.access$700(DbMigrate.java:47)
at com.googlecode.flyway.core.command.DbMigrate$1.doInTransaction(DbMigrate.java:189)
at com.googlecode.flyway.core.command.DbMigrate$1.doInTransaction(DbMigrate.java:138)
at com.googlecode.flyway.core.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:56)
at com.googlecode.flyway.core.command.DbMigrate.migrate(DbMigrate.java:137)
at com.googlecode.flyway.core.Flyway$1.execute(Flyway.java:872)
at com.googlecode.flyway.core.Flyway$1.execute(Flyway.java:819)
at com.googlecode.flyway.core.Flyway.execute(Flyway.java:1200)
at com.googlecode.flyway.core.Flyway.migrate(Flyway.java:819)
at ir.chom.MyApp.<init>(MyApp.java:28)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.glassfish.hk2.utilities.reflection.ReflectionHelper.makeMe(ReflectionHelper.java:1117)
at org.jvnet.hk2.internal.Utilities.justCreate(Utilities.java:867)
at org.jvnet.hk2.internal.ServiceLocatorImpl.create(ServiceLocatorImpl.java:814)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:906)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:898)
at org.glassfish.jersey.server.ApplicationHandler.createApplication(ApplicationHandler.java:300)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:279)
at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:302)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:167)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:349)
at javax.servlet.GenericServlet.init(GenericServlet.java:160)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1280)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1091)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5176)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5460)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3954)
at org.apache.catalina.loader.WebappLoader.backgroundProcess(WebappLoader.java:426)
at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1345)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1530)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1519)
at java.lang.Thread.run(Thread.java:724)
It seems that this is a problem with JDBC that uses autocommit option. This option can be disabled with something like this:
Connection connection = dataSource.getConnection();
Connection.setAutoCommit(false); // Disables auto-commit.
but I don't know how to pass this option to flyway connection. Also if I solve this I think I will have problem with passing password to \c command.
Flyway always operates within the database used in the jdbc connection string.
Once connected, all scripts run within a transaction. As CREATE DATABASE is not supported within transactions, you will not be able to accomplish what you want.
What you can do however, is create a schema instead. Flyway will even do this for you, if you point it at a non-existing one.
I dont know if this is even possible to do in flyway.
Flyway is intended to connect to an already existing database (whether it is empty or not). It also would be a good practice to keep your database creation separate from your database migrations.
Here is a workaround that worked for me (assuming the use of the Maven plugin):
Configure the plugin with two executions. The first execution creates the database. The second execution migrates an existing database.
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>${flyway.version}</version>
<executions>
<execution>
<id>create-db</id>
<goals>
<goal>migrate</goal>
</goals>
<configuration>
<driver>org.postgresql.Driver</driver>
<url>jdbc:postgresql://database-server/</url>
<user>postgres</user>
<password>password</password>
<placeholders>
<DATABASE.NAME>MyDatabase</DATABASE.NAME>
</placeholders>
<locations>
<location>com/foo/bar/database/create</location>
</locations>
</configuration>
</execution>
<execution>
<id>migrate-db</id>
<goals>
<goal>migrate</goal>
</goals>
<configuration>
<driver>org.postgresql.Driver</driver>
<url>jdbc:postgresql://database-server/MyDatabase</url>
<user>postgres</user>
<password>password</password>
<locations>
<location>com/foo/bar/database/migrate</location>
</locations>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
</dependencies>
</plugin>
Then add V1__Created_database.sql to the com/foo/bar/database/create directory. This file contains:
CREATE DATABASE ${DATABASE.NAME}
Flyway can't create database for you.
It can create schema if you didn't create one by
flyway.schemas: schema1,schema2
You can try what is suggested in this issue: https://github.com/flyway/flyway/issues/2556, use the createDatabaseIfNotExist parameter in the mysql url configured in flyway, as below:
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>6.4.1</version>
<configuration>
<url>jdbc:mysql://localhost:3306/<databaseName>?createDatabaseIfNotExist=true</url>
<user>root</user>
<password>root</password>
</configuration>
If u have schema database creation command in V1 of your scripts, flyway can generate it but not database:
flyway -baselineOnMigrate=true -url=jdbc:mysql://localhost/ -schemas=test_db -user=root -password=root_pass -locations=filesystem:/path/to/scrips/ migrate
and similar to this in the script file:
DROP SCHEMA IF EXISTS `test_db` ;
CREATE SCHEMA `test_db` COLLATE utf8_general_ci ;

Categories