web-dev-qa-db-ja.com

flywayでデータベースを作成する方法は?

質問:移行スクリプトで新しいDBを作成してから接続することは可能ですか?どうやって?

私のシナリオ:管理のためにJavaプロジェクト(Jersey2.4 + Tomcat 7 + PostgreSQL 9.3.1 + EclipseLinkを使用したRESTfulアプリケーション)でflywayを使用しようとしていますgitを使用しているさまざまな開発者間の変更。初期化スクリプトを作成して実行しました。

PGPASSWORD='123456' psql -U postgres -f migration/V1__initDB.sql

そしてそれはうまくいきました。問題は、スクリプトで新しいDBを作成できないことです。スクリプトに次の行を含めると:

CREATE DATABASE my_database OWNER postgres ENCODING 'UTF8';

私はこのエラーを受け取ります:

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)

これは、autocommitオプションを使用するJDBCの問題のようです。このオプションは、次のような方法で無効にできます。

Connection connection = dataSource.getConnection();
Connection.setAutoCommit(false);        // Disables auto-commit.

しかし、このオプションをフライウェイ接続に渡す方法がわかりません。また、これを解決したら、\cコマンドにパスワードを渡すのに問題があると思います。

29
sajjadG

Flywayは、常にjdbc接続文字列で使用されるデータベース内で動作します。

接続すると、すべてのスクリプトがトランザクション内で実行されます。 CREATE DATABASEはトランザクション内でサポートされていないため、目的を達成することはできません。

ただし、できることは、代わりにスキーマを作成することです。 Flywayは、存在しないものを指す場合、これを行います。

35
Axel Fontaine

フライウェイでこれが可能かどうかはわかりません。

Flywayは、既存のデータベースに接続することを目的としています(空であるかどうかは関係ありません)。また、データベースの作成をデータベースの移行とは別にすることをお勧めします。

8
stikku

ここで私のために働いた回避策があります(Mavenプラグインの使用を前提としています):

プラグインを2回実行して構成します。最初の実行でデータベースが作成されます。 2回目の実行では、既存のデータベースが移行されます。

    <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>

それから加えて V1__Created_database.sqlからcom/foo/bar/database/createディレクトリ。このファイルには以下が含まれます。

CREATE DATABASE ${DATABASE.NAME}

5
Gili