Flyway で DB マイグレーション

JavaでDBのマイグレーションについて、Flyway か Liquibase で迷って色々なサイトをささっと斜め読みした感じ 「Java」 という点に誘われて Flyway に決定。 Flyway のサイトにある比較では Liquibase は Groovy で書けるらしい。

maven plugin としてでなく Spring の方に組み込んで WAR をデプロイしたタイミングでマイグレーションが行われるようにしました。

事前準備

・データベースが作成されている(テーブルは無い状態)

・テーブル作成済の場合は、フルバックアップしたあと、全テーブル削除。マイグレーション後にデータのみ手動で戻す

pom.xml

<dependency>
    <groupId>com.googlecode.flyway</groupId>
    <artifactId>flyway-core</artifactId>
    <version>2.2.1</version>
</dependency>

applicationContext.xml

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    ・・・
</bean>

<bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate" depends-on="dataSource">
    <property name="dataSource" ref="dataSource" />
    <property name="locations" value="jp/co/xxxx/yyyy/migration" />
    <property name="initOnMigrate" value="true" />
</bean>

<bean id="transactionManager" depends-on="flyway"
class="org.springframework.orm.jpa.JpaTransactionManager">
    ・・・
</bean>

initOnMigrate=true で管理用テーブルが作成される。 locations は デフォルトだと db/migration らしいので、プロジェクトのパッケージに合わせる。

上記の例の場合SQL

src/main/resources/jp/co/xxxx/yyyy/migration

に作る。Java

src/main/java/jp/co/xxxx/yyyy/migration

に作る。 Spring プロジェクトでは SpringJdbcMigration を実装すればいいらしい。

V1_0__update_table.java

public class V1_0__update_table implements SpringJdbcMigration {
    @Override
    public void migrate(JdbcTemplate jt) throws Exception {
        jt.update("更新内容");
    }
}

JavaSQL の同居が可能だけど、バージョン番号はずらす必要あり。 V1__xxxx と V1_0__yyyy は同じバージョン扱い。これで実行すると「同じバージョンがあるぞ!」って怒られる。

Caused by: com.googlecode.flyway.core.api.FlywayException: Found more than one migration with version '1.0'

同一バージョン不可なので実行順番はバージョン順。

Spring 上で使ってみての不満点

・エラーがわかりづらい 何が原因でエラったのかわからない。スタックトレースから読み取れない(ログの出し方が悪い?)