スポンサーリンク

FlywayでSpringBootプロジェクトのDBマイグレーション

FlywayをSpringBootで使う~準備~

データベースを作成する

Windowsであれば、MySQLをインストールしたとにMySQL Command Line Clientが入っています。

mysql> create database happy_library
mysql> create user 'springuser'@'%' identified by 'xxxxx'; -- Creates the
user
mysql> grant all on happy_library.* to 'springuser'@'%';

Flywayをbuild.gradleに設定

flywayはGradleプラグインとして提供されています。(公式サイトはこちら

build.gradleに下記を追記します。

plugins {
    id "org.flywaydb.flyway" version "7.5.2"
}

gradleを更新して、プラグインが適用されたら、flywayの接続情報を追記します。

flyway {
	url = 'jdbc:mysql://localhost:3306/happy_library'
	user = 'springuser'
	password = 'xxxx'
	schemas = ['happy_library']
}

これでflywayの使用準備ができました。

FlywayMigrateを実行する

マイグレーションファイルを置く場所

このままでflywayMigrateを実行すると、下記のようにログが表示されます。

> Task :flywayMigrate
Skipping filesystem location:D:\springhack\happy-library-api\src\main\resources\db\migration (not found).

src\main\resources\db\migration のディレクトリを作成します。

FlywayMigrateでテーブルを作成する

テーブルを作成するDDL(CREATE文)は、次の記事を参考にして作成してください。
>>DDL(Create文の作成)方法

flywayの各機能

Noコマンド概要
1flywayBaseline
2flywayCleanスキーマのすべてのオブジェクト(テーブル、ビュー)を削除する。
3flywayInfoスキーマの現在の状態を表示する。
4flywayMigrateスキーマに対してSQLファイルを実行する。
5flywayRepair履歴テーブルのstautsがFailedになっているバージョンのレコードを削除する。
6flywayUndo有償版(Flyway Teams Edition)限定の機能。直近のスキーマへの変更をも戻せる。
7flywayValidate各SQLファイルのチェックサムについて、履歴テーブルとローカル算出値を比較する。
flywayコマンドの概要

flywayBaseline

flywayClean

> Task :flywayClean

BUILD SUCCESSFUL in 2s

flywayCleanを実行すると、対象スキーマのすべてのオブジェクトが削除されます。テーブル、ビュー、インデックスなどを含みます。

flywayInfo

flywayInfoを実行すると、現在のスキーマの状態を表示します。

> Task :flywayInfo
Schema version: 2
+-----------+---------+-----------------------------+------+---------------------+---------+
| Category  | Version | Description                 | Type | Installed On        | State   |
+-----------+---------+-----------------------------+------+---------------------+---------+
| Versioned | 1       | create-m book               | SQL  | 2021-02-13 10:10:25 | Success |
| Versioned | 2       | insert-m book               | SQL  | 2021-02-13 10:10:25 | Success |
| Versioned | 3       | create-member-lend-tantosha | SQL  |                     | Pending |
+-----------+---------+-----------------------------+------+---------------------+---------+


BUILD SUCCESSFUL in 2s
  • Schema Version: 2...Version 2 のSQLが反映された状態であることを表す。
  • Version,Description...SQLファイルの「V<Version>__<Description>.sql」に該当する部分から取得されます。
  • state...Successはスキーマに反映済み。Failedはスキーマに反映しようとしたが失敗した または 反映時のSQLファイルと現在のSQLファイルの中身が一致しない。Pendingは未だ反映されていない。

flywayMigrate

flywayRepair

flywayUndo

直近のスキーマへの変更を戻せる。有償版(Flyway Teams Edition)のみ使用でき、無償版(Flyway Community Edition)ではエラーとなる。

> Task :flywayUndo FAILED
1 actionable task: 1 executed

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':flywayUndo'.
> Error occurred while executing flywayUndo
  Flyway Teams Edition upgrade required: undo is not supported by Flyway Community Edition.

flywayValidate

Flywayで発生するエラー

No database found to handle jdbc:mysql://localhost:3306/<database名>

使用するMySQLのバージョンと、flyway pluginのバージョンの相性が良くないようです。

flywayのバージョンを下げてみてください。

plugins {
	id 'org.springframework.boot' version '2.6.3'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
	// id "org.flywaydb.flyway" version '8.4.0'
	id "org.flywaydb.flyway" version '8.2.0'
}

・できた組み合わせ

mysql  Ver 8.0.27 : flyway 8.4.0

・できなかった組み合わせ

mysql  Ver 8.0.27 : flyway 8.2.0

Unable to connect to the database. Configure the url, user and password!

DBのURL・ユーザー名・パスワードの設定が見つかりません。
build.gradleに記述します。

flyway {
  url = 'jdbc:mysql://localhost:3306/データベース名'
  user = 'ユーザー名'
  password = 'パスワード'
  schemas = ['スキーマ']
}

Unable to load class 'com.mysql.cj.jdbc.Driver'.

JDBCDriverが見つかりません。
build.gradleで対象のJDBCDriverを依存関係に追加してください。

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'mysql:mysql-connector-java:8.0.27'

	developmentOnly 'org.springframework.boot:spring-boot-devtools'
}

MySQLのJDBCDriverはこちらです。
https://mvnrepository.com/artifact/mysql/mysql-connector-java
バージョンは、MySQLのバージョンと一致させます。

【42000/1064】You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near xxx

> Error occurred while executing flywayMigrate
  
  Migration V3__create-member-lend-tantosha.sql failed
  ----------------------------------------------------
  SQL State  : 42000
  Error Code : 1064
  Message    : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'not null comment '名前'
    , telephone VARCHAR comment '電話番号'
    , reg' at line 3
  Location   : D:\springhack\happy-library-api\src\main\resources\db\migration\V3__create-member-lend-tantosha.sql (D:\springhack\happy-library-api\src\main\resources\db\migration\V3__create-member-lend-tantosha.sql)
  Line       : 10
  Statement  : create table m_tantosha (
    tantosha_id INT auto_increment not null comment '担当者ID'

原因と対策:SQLの文法が誤っている。コンソール内容のnear xxx付近を見直すこと。A5-SQLなどでSQLを実行して正常に通ることを確認する。(VARCHARの文字数の指定がされていない。語句の順番が誤っているなど。)

【28000/1045】Access denied for user 'xxxx'@'localhost' (using password: YES)

> Error occurred while executing flywayMigrate
  
  Unable to obtain connection from database (jdbc:mysql://localhost:3306/happy_library) for user 'springuser': Access denied for user 'springuser'@'localhost' (using password: YES)
  ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  SQL State  : 28000
  Error Code : 1045
  Message    : Access denied for user 'springuser'@'localhost' (using password: YES)
  
  Access denied for user 'springuser'@'localhost' (using password: YES)

原因と対策:ユーザ名に対するパスワードが間違っているため、データベース接続を確立できてなかった。またはユーザ名が間違っている。build.gradleに設定したユーザ名またはパスワードを確認する。

【01S00/0】The server time zone value 'xxx' is unrecognized or represents more than one time zone.

> Error occurred while executing flywayMigrate
  
  Unable to obtain connection from database (jdbc:mysql://localhost:3306/happy_library) for user 'springuser': The server time zone value '���� (�W����)' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specific time zone value if you want to utilize time zone support.
  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  SQL State  : 01S00
  Error Code : 0
  Message    : The server time zone value '���� (�W����)' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specific time zone value if you want to utilize time zone support.
  
  The server time zone value '���� (�W����)' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specific time zone value if you want to utilize time zone support.
  The server time zone value '���� (�W����)' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specific time zone value if you want to utilize time zone support.

原因と対策:

修正前

flyway {
	url = 'jdbc:mysql://localhost:3306/happy_library'
	user = 'springuser'
	password = 'ThePassword'
	schemas = ['happy_library']
}

修正後

flyway {
	url = 'jdbc:mysql://localhost:3306/happy_library?serverTimezone=JST'
	user = 'springuser'
	password = 'ThePassword'
	schemas = ['happy_library']
}

Found non-empty schema(s) xxxxx but no schema history table

Execution failed for task ':flywayMigrate'.
> Error occurred while executing flywayMigrate
  Found non-empty schema(s) `happy_library` but no schema history table. Use baseline() or set baselineOnMigrate to true to initialize the schema history table.

原因と対策:Flywayのスキーマ履歴テーブルが存在していない。Task :flywayBaselineを実行することで、現在のテーブルの状態を基準に、スキーマ履歴テーブルが作成される。

No migrations found. Are your locations set up correctly?

> Task :flywayMigrate
No migrations found. Are your locations set up correctly?

原因と対策:マイグレーションSQLファイルが存在しないと思われている。SQLファイルが適切な場所にあるか、ファイル名のフォーマットが正しい確認する。

  • V<Version>__<Description>.sql
  • <Version> は任意のバージョン番号…半角数値と、ドット . またはアンダーバー _ の組み合わせで指定する。
  • <Description> は任意の説明文

V が小文字だったり、_が1つだったりしないか確認する。

文字化けする

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'not null comment '??'
  , telephone VARCHAR comment '????'
  , registered_at D' at line 3

flywayMigrateしたときに、SQL内の日本語部分が文字化けする場合、MySQL自体の文字コードを設定する必要があります。

>>MySQLの文字化けの対応方法

Error occurred while executing flywayMigrate
Validate failed: Migrations have failed validation
Migration checksum mismatch for migration version 4

適用済みのSQLファイルが変更された時等に発生します。

> Task :flywayMigrate FAILED

Execution failed for task ':flywayMigrate'.
> Error occurred while executing flywayMigrate
  Validate failed: Migrations have failed validation
  Migration checksum mismatch for migration version 4
  -> Applied to database : 1166911454
  -> Resolved locally    : -548108148. Either revert the changes to the migration, or run repair to update the schema history.
flyway_schema_history

上記ログの例では、V4のチェックサムの値が、DB上では"1166911454"(Applied to databaseの値)なのに、ローカルのSQLファイルを元にflywayが算出したところ、"-548108148"(Resolved locallyの値)なので違いますよというエラーです。

解決策としては、DB上の値をResolved locallyの値に変更するか、レコードを消して流し直すかになります。

DB上の値を変更する場合

該当バージョンのSQLファイルを流し直す必要がない場合は、DB上の値をResolved locallyの値に変更します。

この状態でチェックOKになるので、次のSQLファイルが実行されるようになります。

レコードを消して流し直す場合

エラーログの「Migration checksum mismatch for migration version 4」で指摘されているバージョンのレコードを削除します。

こうすることで、V4のSQLは未適用になります。flywayMigrateをすることで、V4が再実行されます。

スポンサーリンク

投稿日:2021年2月10日 更新日:

Copyright© 【Spring Hack】 , 2022 All Rights Reserved Powered by AFFINGER5.