Flyway を使って、PostgreSQL のデータベースをマイグレーションする方法を書いていきます。DBマイグレーションとは、DBのデータを残したまま、テーブル作成やカラム変更などをすることです。
手順1. 依存性の追加
記事「Java共通資源の作成」で作成した pom.xml に、flyway の依存性を追加します。
db-access/pom.xml(追加部分)
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>4.2.0</version>
</dependency>
dependencies タグの下に追加すれば大丈夫です。
手順2. SQLファイルの作成
マイグレーションに使うファイルを作成します。内容はSQLでテーブルを2つ作成する感じです。
db-access/src/main/resources/db/migration/V1__create_tables.sql
create table memo ( id serial primary key, txt varchar(200) not null, updated timestamp not null default current_timestamp, created timestamp not null default current_timestamp ); create table person ( id serial primary key, name varchar(100) not null, updated timestamp not null default current_timestamp, created timestamp not null default current_timestamp );
ファイルの配置場所と名前は、Flyway の規約 に従っています。ファイルの命名規約は以下の通りです。
V<Version>__<NAME>.sql
- V:アルファベット大文字の V です。
- <Version>:数字の 1 や 2_1(アンダースコア区切り)です。SQL ファイルが増えたら、バージョンを上げていきます。
- __:アンダースコア2つです。<Version> と <Name> を区切ります。
- <Name>:任意の文字列とされています。
補足1. 次のマイグレーション
2回目以降は、命名規約に従って SQLファイルを用意します。例えば、V2__Alter.sql, V3__Create.sql, ... といったような感じです。
補足2. Flyway の仕様
SQLファイル は、同じスキーマで1回だけ実行されます。Flyway が、スキーマに管理テーブル「schema_version」を作成してコントロールしてくれます。
管理テーブルがなかったり(違う環境・違うスキーマ)、管理テーブルを削除したりすると、全ての SQLファイルが実行されます。
手順3. Mainクラスの作成
Flyway でマイグレーションをして、memo テーブルにデータを追加するクラスを作成します。
db-access/src/main/java/lib/FlywayMain.java
package lib; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import org.flywaydb.core.Flyway; import jdbc.base.Driver; public class FlywayMain { public static void main(String[] args) throws ClassNotFoundException, SQLException { //-> マイグレーション Flyway flyway = new Flyway(); flyway.setDataSource( "jdbc:postgresql://localhost/test", "neko", "cat" ); flyway.migrate(); //-> INSERT try (Connection con = Driver.connect()) { PreparedStatement ps = con.prepareStatement( "insert into person (name) values (?)" ); ps.setString(1, "Suzuki Taro"); int count = ps.executeUpdate(); System.out.print("INSERT "); System.out.println(count); ps.close(); } } }
flyway.migrate(); で、先ほどのSQLを実行してくれます。一度実行されたSQLは、次回のアプリ起動時には実行されないようになります。Flyway が DB にテーブル schema_version を作成して、実行したSQLの情報などを管理してくれます。
手順4. 動作確認
事前に PostgreSQL を起動して、データベース・ユーザを作成しておきます。作成方法は「DB環境の準備」に書いてます。
リンク先のテーブル memo を既に作成している場合は、psql などで drop table memo; を実行して消しておきます。
test=> \d
リレーションの一覧
スキーマ | 名前 | 型 | 所有者
----------+-------------+------------+--------
public | memo | テーブル | neko
public | memo_id_seq | シーケンス | neko
(2 行)
test=> drop table memo;
DROP TABLE
それから、上の FlywayMain を実行すると、
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. INSERT 1
といった文字列が出力されて、INSERTが1件成功してます。上から3行のメッセージ(SLF4J...)は、Flyway が SLF4J を使っている関係で出力されています。
psql でデータを確認してみます。
test=> select id, name from person; id | name ----+------------- 1 | Suzuki Taro (1 行)
もう一度 FlywayMain を実行するとデータが2件になります。マイグレーションの SQL(V1__create_tables.sql)が実行されるのは一度だけです。