Flyway とは
DB の状態をバージョン管理する為のツールで Spring Boot で簡単に使用することができる。
IntelliJ IDEA で新規プロジェクトを作成する時に依存関係に Flyway を含めると以下が build.gradle
に追加される:
dependencies {
compile('org.flywaydb:flyway-core')
}
Spring Boot の場合 application.yaml
に DB 設定を行うことが必須だ。
SQLite の場合以下のように定義しておく:
spring:
datasource:
url: jdbc:sqlite:./db.sqlite3
driverClassName: org.sqlite.JDBC
Flyway のマイグレーションファイルは (クラスパス)/db/migration
以下に V(バージョン番号)__(説明).sql
の形式で置く。
バージョン番号は公式的には単調増加自然数 (1, 2, ...) のようだが V1_0_2__(説明).sql
のようにするといわゆるマイナーバージョンとリファクタリング番号を記録する (v1.0.2 的な) ことができるようだ。
Spring Boot の場合アプリケーションを実行すると (クラスパス)/db/migration
以下のマイグレーションが自動で走り、今までのマイグレーションの状態は DB の中に flyway_schema_history
テーブルが作成されて管理される。
この flyway_schema_history
テーブルの中を見てみるとどこまでマイグレーションが適用されているか簡単に確認できる。
Flyway の詳しい解説は Flyway使い方メモが分かりやすかった。 SQL ファイルだけでなく Java コードでマイグレーションを記述することができるらしい。 以下、上記ページで解説されていなかった「既存 DB に対するマイグレーション定義」に関して書く。
既存の DB を元にマイグレーションを行う場合
Flyway のマイグレーションはデフォルトでは DB 設計を一から行って新規で作成するアプリケーションの場合が想定されている。
つまり初めは空のデータベースが用意されており V1__Initial.sql
などというファイルを用意し初期テーブルを定義し、その後 V2__Add_delete_flag
などといった感じで初期テーブルに変更を加えていくイメージだ。
だが「既にテーブルが定義されている DB に対しマイグレーションを行った場合」 (まだ flyway_schema_history
が定義されておらず初期投入扱い) は以下の様にエラーが表示される:
Caused by: org.flywaydb.core.api.FlywayException: Found non-empty schema(s) "main" without schema history table! Use baseline() or set baselineOnMigrate to true to initialize the schema history table.
これを回避するためにベースライン (初期状態のバージョン番号) を Flyway に教える必要がある。
application.yaml
に以下を定義する:
spring:
flyway:
baseline-on-migrate: true
baseline-version: 1
baseline-description: Initial
spring.flyway.baseline-on-migrate
が true
の場合既存 DB にマイグレーションを行った場合に spring.flyway.baseline-version
まで適用済みとみなしてくれる。
つまり前述の例の場合 V1__Initial.sql
は実行されずに V2__Add_delete_flag
のみが適用される。
spring.flyway.baseline-description
に定義した文字列はマイグレーション実行後に flyway_schema_history.description
のベースラインまで適用されたことを示す文字列として挿入される。
初期値 (未定義の場合) は << Flyway Baseline >>
のようなのでこのままでも問題ないと思われる。
このあたりの設定の解説は Flyway 公式に書いてある (英語)。