SpringBoot x Flywayで DBマイグレーションを行う.

エキサイト株式会社メディア事業部エンジニアの佐々木です。今回は、SpringBootとFlywayでDBマイグレーションを行います。DBマイグレーションなど後回しにしがちですが、簡単にマイグレーション設定ができますので、手作業を減らしていきましょう。

動作確認環境

動作確認環境は下記になります。これ以外でも動作すると思います。

Java

openjdk 17.0.1 2021-10-19
OpenJDK Runtime Environment (build 17.0.1+12-39)
OpenJDK 64-Bit Server VM (build 17.0.1+12-39, mixed mode, sharing)

Gradle

------------------------------------------------------------
Gradle 7.6.1
------------------------------------------------------------

Build time:   2023-02-24 13:54:42 UTC
Revision:     3905fe8ac072bbd925c70ddbddddf4463341f4b4

Kotlin:       1.7.10
Groovy:       3.0.13
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          17.0.1 (Oracle Corporation 17.0.1+12-39)
OS:           Mac OS X 12.5 aarch64

SpringBoot

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.0.3)

build.gradle

dependencies {
    implementation 'org.flywaydb:flyway-mysql'
    runtimeOnly 'com.mysql:mysql-connector-j'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

通常のDBマイグレーションの設定

設定ファイルの記述

SpringBootの設定ファイル(application.properties or application.yml) に下記のように記述します。 例はYAML形式で記述します。

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/demo_flyway
    username: demo-flyway
    password: demo-flyway-password
    driver-class-name: com.mysql.cj.jdbc.Driver
  flyway:
    baseline-version: 0    // マイグレーション開始バージョン
    enabled: true              // 有効フラグ
    baseline-on-migrate: true        // データベーススキーマにテーブルがある場合でもマイグレーションを実施するかどうか

この例では、接続先のデータベースの設定とDBマイグレーションを行ってくれるflywayの設定が記載されています。

DBマイグレーション用のDDL

DBマイグレーション用のDDLは、下記のようになります。

└── src
    └── main
        └── resources
            └── db
                └── migration
                    ├── V1__create_table1.sql
                    ├── V2__create_table2.sql
                    └── V3__create_table3.sql

今回は、table_1, table_2, table_3 みたいなテーブルを3つ作るマイグレーションを走らせます。(ディレクトリを変更したい場合は、spring.flyway.locationsのプロパティの設定を変更すれば変えられます)

実行

SpringBootを起動すると、DBマイグレーションを実行してくれます。

./gradlew bootRun

...
...
...
2023-03-03T19:37:56.213+09:00  INFO 49352 --- [  restartedMain] o.f.c.i.database.base.BaseDatabaseType   : Database: jdbc:mysql://127.0.0.1:3306/demo_flyway (MySQL 8.0)
2023-03-03T19:37:56.269+09:00  INFO 49352 --- [  restartedMain] o.f.core.internal.command.DbValidate     : Successfully validated 3 migrations (execution time 00:00.009s)
2023-03-03T19:37:56.287+09:00  INFO 49352 --- [  restartedMain] o.f.c.i.s.JdbcTableSchemaHistory         : Creating Schema History table `demo_flyway`.`flyway_schema_history` ...
2023-03-03T19:37:56.330+09:00  INFO 49352 --- [  restartedMain] o.f.core.internal.command.DbMigrate      : Current version of schema `demo_flyway`: << Empty Schema >>
2023-03-03T19:37:56.334+09:00  INFO 49352 --- [  restartedMain] o.f.core.internal.command.DbMigrate      : Migrating schema `demo_flyway` to version "1 - create table1"
2023-03-03T19:37:56.368+09:00  INFO 49352 --- [  restartedMain] o.f.core.internal.command.DbMigrate      : Migrating schema `demo_flyway` to version "2 - create table2"
2023-03-03T19:37:56.395+09:00  INFO 49352 --- [  restartedMain] o.f.core.internal.command.DbMigrate      : Migrating schema `demo_flyway` to version "3 - create table3"

...
...
...

3テーブル分マイグレーションが完了しています。flywayのマイグレーション管理テーブルであるflyway_schema_historyテーブルにもデータが入っています。

1   1 create table1   SQL V1__create_table1.sql   39052902    demo-flyway 2023-03-03 10:37:56 16  1
2   2   create table2   SQL V2__create_table2.sql   -1566294605 demo-flyway 2023-03-03 10:37:56 13  1
3   3   create table3   SQL V3__create_table3.sql   -610966039  demo-flyway 2023-03-03 10:37:56 12  1

すでにテーブルが存在する場合のDBマイグレーションの設定

途中からDBマイグレーションを行いたい場合もあるかと思います。SpringBoot x Flywayでは途中からのDBマイグレーションもできるようになっています。途中からのDBマイグレーションを行う場合は、下記のように設定する必要があります。

- データベース上に1つ以上のテーブルが存在すること
- flyway_schema_history テーブルが存在しないこと
- application.yml (application.properties) に 下記設定を追加すること
  - spring.flyway.baseline-on-migrate=true に設定すること
  - spring.flyway.baseline-version に開始したいバージョン番号を設定する

上記の条件で、それでは設定していきます。

設定ファイルの記述

SpringBootの設定ファイル(application.properties or application.yml) に下記のように記述します。 例はYAML形式で記述します。

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/demo_flyway
    username: demo-flyway
    password: demo-flyway-password
    driver-class-name: com.mysql.cj.jdbc.Driver
  flyway:
    baseline-version: 2    // マイグレーション開始バージョン
    enabled: true              // 有効フラグ
    baseline-on-migrate: true        // データベーススキーマにテーブルがある場合でもマイグレーションを実施するかどうか

spring.flyway.baseline-version=2に設定します。こうすることで、バージョン2以降がマイグレーション対象になります。

既存テーブルの設置

データベースにtable_1を設定します。

CREATE TABLE `table_1` (
    `user_id` bigint NOT NULL AUTO_INCREMENT
    ,`name` varchar(40) COLLATE utf8mb4_general_ci NOT NULL
    ,PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

実行

では、実行してみましょう。

./gradlew bootRun

.... 
2023-03-07T10:31:47.253+09:00  INFO 9048 --- [  restartedMain] o.f.core.internal.command.DbValidate     : Successfully validated 3 migrations (execution time 00:00.011s)
2023-03-07T10:31:47.274+09:00  INFO 9048 --- [  restartedMain] o.f.c.i.s.JdbcTableSchemaHistory         : Creating Schema History table `demo_flyway`.`flyway_schema_history` with baseline ...
2023-03-07T10:31:47.315+09:00  INFO 9048 --- [  restartedMain] o.f.core.internal.command.DbBaseline     : Successfully baselined schema with version: 2
2023-03-07T10:31:47.325+09:00  INFO 9048 --- [  restartedMain] o.f.core.internal.command.DbMigrate      : Current version of schema `demo_flyway`: 2
2023-03-07T10:31:47.330+09:00  INFO 9048 --- [  restartedMain] o.f.core.internal.command.DbMigrate      : Migrating schema `demo_flyway` to version "3 - create table3"
2023-03-07T10:31:47.360+09:00  INFO 9048 --- [  restartedMain] o.f.core.internal.command.DbMigrate      : Successfully applied 1 migration to schema `demo_flyway`, now at version v3 (execution time 00:00.040s)
.... 

ログを見ると、Current version of schema demo_flyway: 2 となっていて、既存の設定バージョンを2になっており、これがflyway_schema_historyに書き込まれます。

version2をベースラインとして、すでに適用済みにという扱いになっています。では、DBマイグレーションされたテーブルを見てみましょう。

table_2は、ベースラインとして適用済みの扱いになっているのでスキップされており、table_3のみが作成されています。これで途中からでもDBマイグレーションが可能です。

まとめ

SpringBoot x Flyway でDBマイグレーションが簡単に行えます。通常のアプリケーション開発に設定を数行追加するだけでサクッと設定できてしまうので、ぜひご活用にください。

最後に

エキサイトではフロントエンジニア、バックエンドエンジニア、アプリエンジニアを随時募集しております。長期インターンも歓迎していますので、興味があれば連絡いただければと思います。

カジュアル面談はこちらになります! meety.net

募集職種一覧はこちらになります!(カジュアルからもOK) www.wantedly.com