Edited at

ことりんと一緒 Springもね - 9. データベースマイグレーション - Flyway


概要 / 説明

ほとんどのWebアプリケーションはデータベースを利用したデータの照会や保管を行います。

そこでデータベース接続を担うレイヤをアプリケーションに設けることを以前実施しました。

- ことりんと一緒 Springもね - 8. リポジトリ層

一方でデータベースのレイアウトはアプリケーションの成長と一緒に変化していく事が一般的です。初期設計から変わらないことはまずありえません。

そこでデータベースの状態を管理しておく事が大事になってきます。

アプリケーションのソースコードはGitなどの管理ツールでバージョン管理が行われていると思います。

同じようにデーターベースの状態をバージョン管理するために使用するツール(フレームワーク)が、今回使用する Flyway です。

flyway-logo-tm.png


前提 / 環境


ランタイムバージョン


  • Kotlin : 1.3.21

  • SpringBoot : 2.1.1.RELEASE


Spring Dependencies


  • Web

  • JDBC

  • JPA

  • Actuator

  • Flyway


開発環境


  • OS : Mac

  • IDE : IntelliJ IDEA

  • Build : Gradle


手順 / 解説


Dependency 追加

まず、Gradle(build.gradle)またはMaven(pom.xml) のそれぞれの定義ファイルを編集し、Flyway の Dependency を追加します。


  • Gradle(build.gradle)の場合

dependencies {

implementation('org.flywaydb:flyway-core')
}


  • Maven(pom.xml)の場合

<dependency>

<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>

また、Spring のプロジェクトを最初に作る際に Spring Initializr を利用する場合は、下図のように Dependencies の項目で Flayway を追加しておくことが可能です。

flyway-initilizr.png


データベース接続定義の記述

Flywayがマイグレーションする対象のデータベースの接続定義やFlywayの動作に関する設定を application.yml (または applicatation.properties) に定義します。

  flyway:

enabled: true
url: jdbc:h2:mem:app;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE
schemas: PUBLIC
user: guest
password: guest
baseline-on-migrate: true
baseline-version: 1.0.0
baseline-description: Initial
locations: classpath:db/migration

項目
説明

enabled
Flyway の実行可否
デフォルト:true(実行する)

url
マイグレーション対象のデータベース接続文字列

schemas
対象のスキーマ
今回対象とするH2DBはデフォルトスキーマが PUBLIC のため指定 (ケースセンシティブのため大文字)

user/password
データベースの接続ユーザID/パスワード

baseline-on-migrate
Flywayのマイグレーションスクリプトの実行バージョンを途中から始めるか否か
デフォルト:false(最初のバージョンから全て実施)

baseline-version
baseline-on-migrate が true の場合に開始するバージョン

baseline-description
baseline-version で実施された場合に記録されるコメント

locations
マイグレーション・スクリプトの配置場所
classpath: クラスパス上の場所を指定
filepath:ファイルシステム上のディレクトリを指定

参考:Flyway Migrate Command1


データベース・マイグレーション・スクリプトの配置

Flywayは配置したSQLを決めたルールに基づいて自動実行しマイグレーションを実施します。とデフォルトではスクリプトの配置場所は、src/main/resources 配下に作成する次のディレクトリとなります。


  • db/migration

db-migration-dir.png

db/migration に配置するSQLファイルは Flyway が認識する命名規約に従うファイル名にする必要があります。

命名規約は以下のようになります。


  • <PREFIX><VERSION>__<DESCRIPTION>.sql

項目
説明

PREFIX
デフォルトは V
Vから始まるファイルをFlywayは走査し実行
flyway.sqlMigrationPrefix プロパティを application.yml に定義し変更可能

VERSION
ドット(.)またはアンダースコア(_)でメジャーバージョンとマイナーバージョンを分離可能
バージョンは1から始める必要あり

DESCRIPTION
説明表記用の項目
該当バージョンでの変更内容を簡単に表現

例:V1.0.0_my_first_flyway.sql


データベース・マイグレーション・スクリプトの作成


V1.0.0-テーブル作成

最初にテーブルを作成するDDLを定義します。


  • db/migration/V1.0.0__Create-InitialTable.sql

CREATE TABLE message (

id VARCHAR(36) NOT NULL PRIMARY KEY,
title VARCHAR(255),
message VARCHAR(255),
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

アプリケーションを実行します。

$ ./gradlew clean bootRun

. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.1.RELEASE)
:
:
2019-03-28 13:26:52.822 INFO 7128 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 5.2.4 by Boxfuse
2019-03-28 13:26:53.118 INFO 7128 --- [ main] o.f.c.internal.database.DatabaseFactory : Database: jdbc:h2:mem:app (H2 1.4)
2019-03-28 13:26:53.254 INFO 7128 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.018s)
2019-03-28 13:26:53.280 INFO 7128 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table: "PUBLIC"."flyway_schema_history"
2019-03-28 13:26:53.329 INFO 7128 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema "PUBLIC": << Empty Schema >>
2019-03-28 13:26:53.331 INFO 7128 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema "PUBLIC" to version 1.0.0 - Create-InitialTable
2019-03-28 13:26:53.358 INFO 7128 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.089s)
:
:

起動時ログから、Flyway によるテーブル作成処理 Migrating schema "PUBLIC" to version 1.0.0 - Create-InitialTable が実施されたことが確認できます。

また、以下のようにH2DBコンソールを確認すると下記のように、Flywayの履歴テーブルに 1.0.0 の処理が記録されている事が分かります。

flyway_1_0_0.png


V1.1.0-データ追加

次に作成したテーブルに対してデータを追加するSQLを定義します。


  • db/migration/V1.1.0__Insert-InitialData.sql

INSERT INTO message(id, title, message) VALUES ('7b23257c-e9d9-4d1e-ba79-01f8b8715ba9', 'INIT', 'Inserted by FLYWAY');

INSERT INTO message(id, title, message) VALUES ('12345678-e9d9-4d1e-ba79-01f8b8715ba9', 'INIT', 'Inserted by FLYWAY');

先程と同様にアプリケーションを実行します。

$ ./gradlew clean bootRun

. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.1.RELEASE)
:
:
2019-03-28 13:43:30.226 INFO 7430 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 5.2.4 by Boxfuse
2019-03-28 13:43:30.431 INFO 7430 --- [ main] o.f.c.internal.database.DatabaseFactory : Database: jdbc:h2:mem:app (H2 1.4)
2019-03-28 13:43:30.588 INFO 7430 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 2 migrations (execution time 00:00.029s)
2019-03-28 13:43:30.617 INFO 7430 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table: "PUBLIC"."flyway_schema_history"
2019-03-28 13:43:30.658 INFO 7430 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema "PUBLIC": << Empty Schema >>
2019-03-28 13:43:30.659 INFO 7430 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema "PUBLIC" to version 1.0.0 - Create-InitialTable
2019-03-28 13:43:30.694 INFO 7430 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema "PUBLIC" to version 1.1.0 - Insert-InitialData
2019-03-28 13:43:30.713 INFO 7430 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 2 migrations to schema "PUBLIC" (execution time 00:00.107s)

起動時ログから、追加したマイグレーションスクリプトが実行されている事が確認できます。

- Migrating schema "PUBLIC" to version 1.0.0 - Create-InitialTable

- Migrating schema "PUBLIC" to version 1.1.0 - Insert-InitialData

H2DBコンソールを確認すると、履歴テーブルに2つのマイグレーション処理が実行された事が記録されています。

flyway_1_1_0.png

また、作成した MESSAGE テーブルを照会するとマイグレーション・スクリプトとして定義していたSQLが反映され、データが追加されている事が確認できます。

flyway_1_1_0-select-data.png


まとめ / 振り返り

Migration-1-2.png

アプリケーションの開発時には頻繁にデータベースレイアウトが変更になったり、それに伴うデータの登録などの作業が頻発しがちです。

また、どのタイミング(要件)でのレイアウト変更なのか管理する作業も必要になってきます。

このFlywayを利用してデータベース管理を行うと、そのような作業の手間が削減できるのではないでしょうか。


今回のソース