SpringBootでflyway
flywayを利用すると、マイグレーション管理を行えます
- flyway_schema_history
- 管理テーブル
- 初期マイグレート時に作成される
- 主にバージョン番号を管理している
依存の追加
implementation 'org.flywaydb:flyway-core'
// compileOnly 'org.flywaydb:flyway-core' こっちだと実行時に動きません
プロパティファイルを修正して
マイグレーションの有効設定をする
flyway:
enable: true
baseline-on-migrate: true # 既にあるテーブルなどがあるデータベースでもマイグレーションを実行する
flywayはテーブル設計を1から行うために作られているので、通常は何かしらのテーブルがある状態で行うとエラーになる。
そのため他に定義済のテーブルがあってもエラー無く進めるために設定する
参考
マイグレーションファイルの準備
書式
- X-<Version>__<Description>.sql
- X
- V:デフォルト
- R:リピータブルマイグレーション(マイグレーションファイルのチェックサムが変わるごとにマイグレーションが適用される)
- <Version>
- バージョン番号と説明はアンダーバーを2つ続けて区切る
- <Description>
- 説明の記載
- X
resources/db/migrationフォルダに投入する
例:
-
R__1_create_tables.sql
-
R__2_insert_code.sql
-
R__3_insert_master.sql
-
起動するとマイグレーションが実行される
-
通常起動のたびにマイグレーションが実行されては困ってしまう
現状DBにテーブルがあるが、create対象のテーブルはない
V1__create_table.sql
V__2_insert_sample.sql
→ 普通に実行
public.flyway_schema_historyのみ作成された
versionは1
おそらくV2以降のものが実行されるとおもう
V1はそもそも予約的なものでflyway_schema_historyの作成を担っているのでは?
2回目
V1__
V2__
V1が実行されたない
Caused by: org.postgresql.util.PSQLException: ERROR: relation "samples" does not exist
既にversionが1なのでV1__がスキップされていた
V2__
V3__
にしたところ実行された
じゃあこれでバージョンが2になるの?というとそういうことではない
みたところバージョンが3まで進んでいるので、次回以降V4__からが対象になる
わかったこと
- flyway_schema_historyのバージョンが1の時は、V1が実行されない
- 同じバージョン番号を持ったファイル名、V1__ V1__だとエラーになる
もう一度挑戦
テーブルは空の状態で
V2__create
v3__insert
これが流れるか確認する
流れた。これなら問題ない
もう一度確認のため
V1__
V2__
でテーブル空で行う
やはりV1__がスキップされる
えらーになった
Caused by: org.flywaydb.core.internal.command.DbMigrate$FlywayMigrateException: Migration V2__insert_sample.sql failed
おそらくデフォルト
いかの設定がデフォルトで動いている可能性を感じる
baseline-version: 1
これは
flyway:
enable: true
baseline-on-migrate: true # 既にあるテーブルなどがあるデータベースでもマイグレーションを実行する
このbaseline-on-migrateがtrueの時に、baseline-versionまでの実行をスキップ(実際にはflyway_schema_historyのバージョンの登録値を設定している)してくれる
そのためversion: 2 を指定すれば V3__からが対象のファイルと認識される
確認のため、このversion: 0にして行う
V1__
V2__
はそのままだ
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://192.168.11.13:5432/school
username: kakine
password: teitoku
flyway:
enable: true
baseline-on-migrate: true # 既にあるデータベースでもマイグレーションを実行する
baseline-version: 0
結果
やはりそうだ
V1__もV2__も実行された
一見V1からファイルを始めるべきだろうと思っていても、実は思わぬ落とし穴があったわけです
ところでファイルの名にはVとRがまたはUなんかもあったか?
VはデフォルトのVだ。さてRはリピータブルマイグレーションという。マイグレーションファイルのチェックサムが変わるごとにマイグレーションが適応されるものだ
Rというのはバージョン番号で管理しない
チェックサムについて
まずこれだとR1__R2__が無視された。V1__V2__までの実行が確認できた
次にすべてRにして実行した
なんと何も作成されなかった
これはRがバージョン番号で管理しないため、ファイル名をR__hoge_fuga.sqlにする必要があるからだ。
V1__
V2__
R__3
R__4
今度はmasterテーブル含めて作成された。
そして管理テーブルではバージョンに番号が入ってないことも確認できた。
ではこの状態でファイルを変更して実行してみる
ファイルの変更があったためか実行された
今回はインサート文なので既存のレコード行に該当するレコードもインサートされた。
次にファイルの変更をせずに実行しよう
このときにインサートが行われていなければ、ファイルの変更時のみ反応していることがわかる
予想通り変わることはなかった
参考