Flywayというデータベースマイグレーションライブラリを使ってみました。

環境など


  • Play Framework 2.6.11
  • Flyway 5.0.7

Scala + Play FrameworkでやってるんですがPlay Framework向けにflyway-playというライブラリがあります。今回はこれを使いま…せんでした。若干最新バージョンから遅れをとっているのと、マイグレーション用のSQLを格納するディレクトリが決まってたみたいなので、なんかそこがちょっとな~と思ったのがあります。結局、同じディレクトリ構成にしてしまったのですが…。

build.sbt


build.sbtのlibraryDependenciesに下記を記述。バージョンはサイトの方で確認してください。

1
"org.flywaydb" % "flyway-core" % "5.0.7",

コード書く


マイグレーションのSQLを読んで実行するコードを書きます。ドキュメントを見るとファイルをパス指定で読み込む方法とJavaのクラスパスに従って読み込む方法があるのですが、クラスパスに従って読み込む方法だとどうもうまくいかなかった(ディレクトリ構成も合わせたんだけどな)ので、ファイルのパスを指定することにしました。これは私がJavaド素人というのが最大の要因ですし、日本語のいくつかの記事だと普通にクラスパスでやってるので私の問題です。

というわけで、ファイルパスを指定してSQLを読み込みます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.flywaydb.core.Flyway

class DBMigrate {

val flyway = new Flyway()
//データベース接続情報セット
flyway.setDataSource("jdbc:mariadb://127.0.0.1/testschema", "user", "pass")

//SQLファイルが存在するディレクトリをセット
flyway.setLocations("filesystem:" + System.getProperty("user.dir") + "/conf/db/migration")

//マイグレーション実行
flyway.migrate()

}

こんな感じにしてみました。今回はSQLは/conf/db/migrationに格納しました。

System.getProperty("user.dir")でプロジェクトのカレントディレクトリが取得できるので、その後ろにディレクトリのパスを足してます。前述のとおりこれはflyway-playのデフォルトの設定と同じです。結局同じところに配置するなら、おとなしくライブラリ使えばよかったのではないか…

わかんなかったらAPI見ながらやったらいいです。

SQLを格納する


前述のディレクトリ内にSQLを格納します。今回はV1__Initialize.sqlという名前にしました。はじめアンダースコアを1つしか書いておらずエラーがでたのですが、アンダースコアは2つ書かなければなりません。ドキュメントはよく読みましょう。その他詳しい命名にはドキュメント見てください。

実行してみる


これで実行するとちゃんとテーブルができます。また、マイグレーションのログ自身も下記のようにDBで管理されるようになってます。

コンソールには何も表示されませんでしたが、logbackを設定していると下記のようにマイグレーションのログがでてました。

1
2
3
4
5
2018-02-03 22:53:03 +0900 [INFO] from org.flywaydb.core.internal.database.DatabaseFactory - Database: jdbc:mariadb://address=(host=127.0.0.1)(port=3306)(type=master)/testschema (MySQL 10.2)
2018-02-03 22:53:03 +0900 [INFO] from org.flywaydb.core.internal.command.DbValidate - Successfully validated 1 migration (execution time 00:00.009s)
2018-02-03 22:53:03 +0900 [INFO] from org.flywaydb.core.internal.command.DbMigrate - Current version of schema `testschema`: << Empty Schema >>
2018-02-03 22:53:03 +0900 [INFO] from org.flywaydb.core.internal.command.DbMigrate - Migrating schema `testschema` to version 1 - Initialize
2018-02-03 22:53:03 +0900 [INFO] from org.flywaydb.core.internal.command.DbMigrate - Successfully applied 1 migration to schema `testschema` (execution time 00:00.079s)

この後に再度実行すると下記のようにマイグレーションの不要とのログがでてました。

1
2018-02-03 23:08:19 +0900 [INFO] from org.flywaydb.core.internal.command.DbMigrate - Schema `testschema` is up to date. No migration necessary.

SQLを変更して実行してみる


テーブルに変更が入ると当然別ファイルでALTER文を記述することになると思うのですが、せっかくなので作成したテーブルをDROPした上で既に実行済みのV1__Initialize.sqlの中身を変更して実行すると…。

1
Migration checksum mismatch for migration version 1

ああ、やっぱり怒られるんですね。flywayの履歴テーブルから対象のレコードを削除して実行するとうまくいきました。

まとめ


なんか、あんまりScalaに関係ない内容だったんですが、まあええでしょう。play-slick-evolutionだとSQLファイルの命名が数値でしたがこちらだとファイル名にわかりやすい名前を付けることができていいですね。どうでもいいのですが、あのペイントで書いたようなロゴがうまいことふわっとふわふわ感を表現していて、私は好きです。