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("更新内容"); } }
Java と SQL の同居が可能だけど、バージョン番号はずらす必要あり。 V1__xxxx と V1_0__yyyy は同じバージョン扱い。これで実行すると「同じバージョンがあるぞ!」って怒られる。
Caused by: com.googlecode.flyway.core.api.FlywayException: Found more than one migration with version '1.0'
同一バージョン不可なので実行順番はバージョン順。
Spring 上で使ってみての不満点
・エラーがわかりづらい 何が原因でエラったのかわからない。スタックトレースから読み取れない(ログの出し方が悪い?)