これは、なにをしたくて書いたもの?
以前に、Flywayを試してみました。
データベースマイグレーションツール、Flywayを試してみる - CLOVER🍀
今回は、フレームワークに組み込んで使うパターンとしてQuarkusのExtensionがあるのでこちらを試してみました。
Quarkus Flyway Extension
QuarkusのFlyway Extensionについてのドキュメントはこちら。
実行方法は、以下の2つがあります。
quarkus.flyway.migrate-at-start
をtrue
に設定し、アプリケーションの起動時にFlywayを自動実行するFlyway
のインスタンスをインジェクションし、Flyway#migrate
をプログラム内で呼び出して実行する
マイグレーションのデフォルトの配置先は、db/migration
です。
Flywayを使うために必要なExtensionはDatasource、というかJDBCです。
あとは複数のデータソースを扱う方法や、Hibernateと組み合わせるといった話もあるようですが。
Schema Migration with Flyway / Multiple datasources
Schema Migration with Flyway / Flyway and Hibernate ORM
Using Hibernate ORM and JPA / Automatically transitioning to Flyway to Manage Schemas
今回は、以下の内容で扱ってみたいと思います。
- Flywayはアプリケーションの起動時に自動実行し、単一のデータソースに適用する
- 通常の起動とテストでの起動で、別々の設定にする
- アプリケーションは、JDBCではなくReactive SQL Clientを使ってデータベースにアクセスする
- 使用するデータベースは、MySQLとする
Quarkus - Reactive SQL Clients
環境
今回の環境は、こちら。
$ java --version openjdk 17.0.1 2021-10-19 OpenJDK Runtime Environment (build 17.0.1+12-Ubuntu-120.04) OpenJDK 64-Bit Server VM (build 17.0.1+12-Ubuntu-120.04, mixed mode, sharing) $ mvn --version Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 17.0.1, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "5.4.0-96-generic", arch: "amd64", family: "unix"
MySQLのバージョンはこちらで、172.17.0.2で動作しているものとします。
$ mysql --version mysql Ver 8.0.28 for Linux on x86_64 (MySQL Community Server - GPL)
プロジェクトを作成する
では、Quarkusプロジェクトを作成します。Flyway Extensionを使うのに最低限必要なのは、flyway
、そしてjdbc-[使用するデータベース]
です。
$ mvn io.quarkus.platform:quarkus-maven-plugin:2.6.2.Final:create \ -DprojectGroupId=org.littlewings \ -DprojectArtifactId=flyway-migration \ -DprojectVersion=0.0.1-SNAPSHOT \ -Dextensions="resteasy-reactive,resteasy-reactive-jackson,flyway,jdbc-mysql,reactive-mysql-client"
その他は、今回のアプリケーションを書くのに選んだものです。
Extensionの表示。
[INFO] Looking for the newly published extensions in registry.quarkus.io [INFO] ----------- [INFO] selected extensions: - io.quarkus:quarkus-jdbc-mysql - io.quarkus:quarkus-flyway - io.quarkus:quarkus-resteasy-reactive - io.quarkus:quarkus-reactive-mysql-client - io.quarkus:quarkus-resteasy-reactive-jackson [INFO] applying codestarts... [INFO] 📚 java 🔨 maven 📦 quarkus 📝 config-properties 🔧 dockerfiles 🔧 maven-wrapper 🚀 resteasy-reactive-codestart
プロジェクト内に移動。
$ cd flyway-migration
Maven依存関係は、こちら。
<dependencies> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-jdbc-mysql</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-flyway</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy-reactive</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-reactive-mysql-client</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy-reactive-jackson</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-arc</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-junit5</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.rest-assured</groupId> <artifactId>rest-assured</artifactId> <scope>test</scope> </dependency> </dependencies>
生成されたソースコードは、削除しておきます。
$ rm src/main/java/org/littlewings/* src/test/java/org/littlewings/*
あとはプログラムとマイグレーションを作成していきます。
マイグレーションとプログラムを書く
お題はFlywayなので、まずはマイグレーションを作りましょう。
src/main/resources/db/migration/V1__create_book_table.sql
create table book ( isbn varchar(14), title varchar(255), price int, primary key(isbn) );
書籍をテーマにしましょう。
こちらのテーブルに対して、Entity的なクラスと
src/main/java/org/littlewings/quarkus/flyway/Book.java
package org.littlewings.quarkus.flyway; public class Book { String isbn; String title; int price; public static Book create(String isbn, String title, int price) { Book book = new Book(); book.setIsbn(isbn); book.setTitle(title); book.setPrice(price); return book; } // getter/setterは省略 }
RESTEasy Reactiveを使ったリソースクラスを作成。
src/main/java/org/littlewings/quarkus/flyway/BookResource.java
package org.littlewings.quarkus.flyway; import java.net.URI; import javax.inject.Inject; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import io.smallrye.mutiny.Multi; import io.smallrye.mutiny.Uni; import io.vertx.mutiny.mysqlclient.MySQLPool; import io.vertx.mutiny.sqlclient.Row; import io.vertx.mutiny.sqlclient.RowSet; import io.vertx.mutiny.sqlclient.Tuple; import org.jboss.resteasy.reactive.RestPath; import org.jboss.resteasy.reactive.RestResponse; @Path("book") public class BookResource { @Inject MySQLPool mysqlClient; @GET @Produces(MediaType.APPLICATION_JSON) public Multi<Book> findAll() { return mysqlClient .preparedQuery("select isbn, title, price from book order by price desc") .execute() .onItem() .transformToMulti(Multi.createFrom()::iterable) .onItem() .transform(row -> Book.create(row.getString("isbn"), row.getString("title"), row.getInteger("price"))); } @GET @Path("{isbn}") @Produces(MediaType.APPLICATION_JSON) public Uni<Book> findOne(@RestPath String isbn) { return mysqlClient .preparedQuery("select isbn, title, price from book where isbn = ?") .execute(Tuple.of(isbn)) .onItem() .transform(RowSet::iterator) .onItem() .transform(iterator -> { if (iterator.hasNext()) { Row row = iterator.next(); return Book.create(row.getString("isbn"), row.getString("title"), row.getInteger("price")); } else { return null; } }); } @PUT @Path("{isbn}") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Uni<RestResponse<?>> put(Book book) { return mysqlClient .preparedQuery("insert into book(isbn, title, price) values(?, ?, ?)") .execute(Tuple.of(book.getIsbn(), book.getTitle(), book.getPrice())) .onItem() .transform(rows -> RestResponse.created(URI.create("/book/" + book.isbn))); } @DELETE @Path("{isbn}") public Uni<Boolean> delete(@RestPath String isbn) { return mysqlClient .preparedQuery("delete from book where isbn = ?") .execute(Tuple.of(isbn)) .onItem() .transform(rows -> rows.rowCount() == 1); } }
アプリケーションの設定は、このようにしました。
src/main/resources/application.properties
# JDBC, Reactive SQL Client Common quarkus.datasource.db-kind=mysql quarkus.datasource.username=kazuhira quarkus.datasource.password=password # JDBC quarkus.datasource.jdbc.url=jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8&characterSetResults=utf-8&connectionCollation=utf8mb4_bin # Flyway quarkus.flyway.migrate-at-start=true # Reactive SQL Client quarkus.datasource.reactive.url=mysql://172.17.0.2:3306/practice?characterEncoding=utf8mb4&charset=utf8mb4&collation=utf8mb4_bin
データベースの種類やユーザー名、パスワードはJDBC、Reactive SQL Clientを問わず同じ項目になります。
# JDBC, Reactive SQL Client Common quarkus.datasource.db-kind=mysql quarkus.datasource.username=kazuhira quarkus.datasource.password=password
JDBC接続URL。こちらは、今回はFlywayが使います。
# JDBC quarkus.datasource.jdbc.url=jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8&characterSetResults=utf-8&connectionCollation=utf8mb4_bin
Reactive SQL Clientの場合はこちら。
# Reactive SQL Client quarkus.datasource.reactive.url=mysql://172.17.0.2:3306/practice?characterEncoding=utf8mb4&charset=utf8mb4&collation=utf8mb4_bin
Vert.x Reactive MySQL Clientの方が、より厳密にMySQLのCharsetとCollationを扱うようなのですが。
Reactive MySQL Client / Configuration
残念ながら、今回使おうと思ったCollation(utf8mb4_0900_bin
)はサポートしていませんでした…。
なので、utf8mb4_bin
を指定しています。
指定しないと、Vert.x Reactive MySQL ClientのデフォルトのCharsetとCollationになるみたいなんですよね。
// set connection collation to utf8_general_ci instead of the default collation utf8mb4_general_ci
ちなみに、ドキュメントを見るとURLで指定できる項目はやや少なめに見えるのですが
Currently, the client supports the following parameter keywords in connection uri (keys are case-insensitive):
実際はもっと指定できそうです。
ムリにcollation=utf8mb4_0900_bin
と指定すると、例外がスローされます。
Caused by: java.lang.IllegalArgumentException: Unsupported collation: utf8mb4_0900_bin at io.vertx.mysqlclient.MySQLConnectOptions.setCollation(MySQLConnectOptions.java:137) at io.vertx.mysqlclient.MySQLConnectOptionsConverter.fromJson(MySQLConnectOptionsConverter.java:40) at io.vertx.mysqlclient.MySQLConnectOptions.<init>(MySQLConnectOptions.java:90) at io.vertx.mysqlclient.MySQLConnectOptions.fromUri(MySQLConnectOptions.java:55) at io.quarkus.reactive.mysql.client.runtime.MySQLPoolRecorder.toMySQLConnectOptions(MySQLPoolRecorder.java:100) at io.quarkus.reactive.mysql.client.runtime.MySQLPoolRecorder.initialize(MySQLPoolRecorder.java:63) at io.quarkus.reactive.mysql.client.runtime.MySQLPoolRecorder.configureMySQLPool(MySQLPoolRecorder.java:45) at io.quarkus.deployment.steps.ReactiveMySQLClientProcessor$build360423335.deploy_0(Unknown Source) at io.quarkus.deployment.steps.ReactiveMySQLClientProcessor$build360423335.deploy(Unknown Source) ... 51 more
ちょっと余談でした。
Flywayの設定は、今回はこれだけです。
# Flyway quarkus.flyway.migrate-at-start=true
これで、アプリケーションの起動時にFlywayが実行されます。
動作確認してみる
それでは、動作確認してみましょう。
まだこの時点では、対象のデータベースにはなにもありません。
mysql> use practice; Database changed mysql> show tables; Empty set (0.01 sec)
パッケージングして
$ mvn package
起動。
$ java -jar target/quarkus-app/quarkus-run.jar
自動するとすぐにマイグレーションが適用されます。
2022-01-21 01:33:24,502 INFO [org.fly.cor.int.lic.VersionPrinter] (main) Flyway Community Edition 8.1.0 by Redgate 2022-01-21 01:33:24,520 INFO [org.fly.cor.int.dat.bas.BaseDatabaseType] (main) Database: jdbc:mysql://172.17.0.2:3306/practice (MySQL 8.0) 2022-01-21 01:33:24,624 INFO [org.fly.cor.int.sch.JdbcTableSchemaHistory] (main) Creating Schema History table `practice`.`flyway_schema_history` ... 2022-01-21 01:33:25,120 INFO [org.fly.cor.int.com.DbMigrate] (main) Current version of schema `practice`: << Empty Schema >> 2022-01-21 01:33:25,140 INFO [org.fly.cor.int.com.DbMigrate] (main) Migrating schema `practice` to version "1 - create book table" 2022-01-21 01:33:25,420 INFO [org.fly.cor.int.com.DbMigrate] (main) Successfully applied 1 migration to schema `practice`, now at version v1 (execution time 00:00.322s)
適用されたExtension。
2022-01-21 01:33:25,719 INFO [io.quarkus] (main) Installed features: [agroal, cdi, flyway, jdbc-mysql, narayana-jta, reactive-mysql-client, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, vertx]
データベースを確認すると、テーブルが追加され、マイグレーションの履歴も登録されています。
mysql> show tables; +-----------------------+ | Tables_in_practice | +-----------------------+ | book | | flyway_schema_history | +-----------------------+ 2 rows in set (0.00 sec) mysql> select * from flyway_schema_history; +----------------+---------+-------------------+------+----------------------------------------+-----------+--------------+---------------------+----------------+---------+ | installed_rank | version | description | type | script | checksum | installed_by | installed_on | execution_time | success | +----------------+---------+-------------------+------+----------------------------------------+-----------+--------------+---------------------+----------------+---------+ | 1 | 1 | create book table | SQL | db/migration/V1__create_book_table.sql | 657681960 | kazuhira | 2022-01-20 16:33:25 | 208 | 1 | +----------------+---------+-------------------+------+----------------------------------------+-----------+--------------+---------------------+----------------+---------+ 1 row in set (0.00 sec)
データを登録して動作確認。
$ curl -i -XPUT -H 'Content-Type: application/json' localhost:8080/book/978-4798161488 -d '{ "isbn": "978-4798161488", "title": "MySQL徹底入門 第4版 MySQL 8.0対応", "price": 4180 }' HTTP/1.1 201 Created Content-Type: application/json Location: /book/978-4798161488 content-length: 0 $ curl -i -XPUT -H 'Content-Type: application/json' localhost:8080/book/978-4798147406 -d '{ "isbn": "978-4798147406", "title": "詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド", "price": 3960 }' HTTP/1.1 201 Created Content-Type: application/json Location: /book/978-4798147406 content-length: 0 $ curl -i -XPUT -H 'Content-Type: application/json' localhost:8080/book/978-4295000297 -d '{ "isbn": "978-4295000297", "title": "MySQL 即効クエリチューニング", "price": 1980 }' HTTP/1.1 201 Created Content-Type: application/json Location: /book/978-4295000297 content-length: 0
データを見てみます。
$ curl -s localhost:8080/book | jq [ { "isbn": "978-4798161488", "title": "MySQL徹底入門 第4版 MySQL 8.0対応", "price": 4180 }, { "isbn": "978-4798147406", "title": "詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド", "price": 3960 }, { "isbn": "978-4295000297", "title": "MySQL 即効クエリチューニング", "price": 1980 } ] $ curl -s localhost:8080/book/978-4798147406 | jq { "isbn": "978-4798147406", "title": "詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド", "price": 3960 }
削除。
$ curl -i -XDELETE localhost:8080/book/978-4295000297 HTTP/1.1 200 OK content-length: 4 Content-Type: text/plain;charset=UTF-8
確認。
$ curl -s localhost:8080/book | jq [ { "isbn": "978-4798161488", "title": "MySQL徹底入門 第4版 MySQL 8.0対応", "price": 4180 }, { "isbn": "978-4798147406", "title": "詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド", "price": 3960 } ]
OKですね。
1度ここでアプリケーションを終了させます。
マイグレーションを追加してみる
もうひとつ、マイグレーションを追加してみましょう。
src/main/resources/db/migration/V2__create_account_table.sql
create table account ( id int, name varchar(50), registered datetime, about varchar(255), primary key(id) );
パッケージングして
$ mvn package
実行。
$ java -jar target/quarkus-app/quarkus-run.jar
起動時に、新しいマイグレーションが適用されました。
2022-01-21 01:41:07,579 INFO [org.fly.cor.int.lic.VersionPrinter] (main) Flyway Community Edition 8.1.0 by Redgate 2022-01-21 01:41:07,595 INFO [org.fly.cor.int.dat.bas.BaseDatabaseType] (main) Database: jdbc:mysql://172.17.0.2:3306/practice (MySQL 8.0) 2022-01-21 01:41:07,707 INFO [org.fly.cor.int.com.DbMigrate] (main) Current version of schema `practice`: 1 2022-01-21 01:41:07,732 INFO [org.fly.cor.int.com.DbMigrate] (main) Migrating schema `practice` to version "2 - create account table" 2022-01-21 01:41:07,949 INFO [org.fly.cor.int.com.DbMigrate] (main) Successfully applied 1 migration to schema `practice`, now at version v2 (execution time 00:00.277s)
テーブルと履歴の確認。
mysql> show tables; +-----------------------+ | Tables_in_practice | +-----------------------+ | account | | book | | flyway_schema_history | +-----------------------+ 3 rows in set (0.00 sec) mysql> select * from flyway_schema_history; +----------------+---------+----------------------+------+-------------------------------------------+------------+--------------+---------------------+----------------+---------+ | installed_rank | version | description | type | script | checksum | installed_by | installed_on | execution_time | success | +----------------+---------+----------------------+------+-------------------------------------------+------------+--------------+---------------------+----------------+---------+ | 1 | 1 | create book table | SQL | db/migration/V1__create_book_table.sql | 657681960 | kazuhira | 2022-01-20 16:33:25 | 208 | 1 | | 2 | 2 | create account table | SQL | db/migration/V2__create_account_table.sql | 1435889679 | kazuhira | 2022-01-20 16:41:07 | 130 | 1 | +----------------+---------+----------------------+------+-------------------------------------------+------------+--------------+---------------------+----------------+---------+ 2 rows in set (0.00 sec)
OKですね。
この確認は、ここまでにしておきます。
テストで使ってみる
最後に、テストでも使ってみたいと思います。
まず、テスト時と通常のアプリケーションの実行時で、設定を分けてみます。
src/main/resources/application.properties
# JDBC, Reactive SQL Client Common quarkus.datasource.db-kind=mysql quarkus.datasource.username=kazuhira quarkus.datasource.password=password # JDBC quarkus.datasource.jdbc.url=jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8&characterSetResults=utf-8&connectionCollation=utf8mb4_bin # Flyway quarkus.flyway.migrate-at-start=true # Reactive SQL Client quarkus.datasource.reactive.url=mysql://172.17.0.2:3306/practice?characterEncoding=utf8mb4&charset=utf8mb4&collation=utf8mb4_bin ## test %test.quarkus.datasource.username=testuser %test.quarkus.datasource.password=password %test.quarkus.datasource.jdbc.url=jdbc:mysql://172.17.0.2:3306/test?characterEncoding=utf-8&characterSetResults=utf-8&connectionCollation=utf8mb4_bin %test.quarkus.datasource.reactive.url=mysql://172.17.0.2:3306/test?characterEncoding=utf8mb4&charset=utf8mb4&collation=utf8mb4_bin %test.quarkus.flyway.locations=db/migration,test/db/migration
%test
というのは、test
Profile時に有効になる設定ですね。
Configuration Reference / Profiles
接続先は、テスト用にここまでに出てきた項目を定義しているのですが
%test.quarkus.datasource.username=testuser %test.quarkus.datasource.password=password %test.quarkus.datasource.jdbc.url=jdbc:mysql://172.17.0.2:3306/test?characterEncoding=utf-8&characterSetResults=utf-8&connectionCollation=utf8mb4_bin %test.quarkus.datasource.reactive.url=mysql://172.17.0.2:3306/test?characterEncoding=utf8mb4&charset=utf8mb4&collation=utf8mb4_bin
今回は、さらにFlyway用の設定を追加しました。
%test.quarkus.flyway.locations=db/migration,test/db/migration
この設定で、db/migration
とtest/db/migration
の2つのクラスパス上のマイグレーションが対象になります。
テスト用のマイグレーションとして、初期データ登録を入れてみました。
src/test/resources/test/db/migration/V99__insert_test_data.sql
insert into book(isbn, title, price) values('978-4798161488', 'MySQL徹底入門 第4版 MySQL 8.0対応', 4180);
また、以下の設定はProfile共通で有効になるので、テスト時にもFlywayは自動実行されます。
# Flyway quarkus.flyway.migrate-at-start=true
作成したテストコードは、こちら。
src/test/java/org/littlewings/quarkus/flyway/BookResourceTest.java
package org.littlewings.quarkus.flyway; import java.util.List; import io.quarkus.test.common.http.TestHTTPEndpoint; import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; import static io.restassured.RestAssured.given; import static io.restassured.RestAssured.when; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; @QuarkusTest @TestHTTPEndpoint(BookResource.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class BookResourceTest { @Test @Order(1) public void initialFindAll() { given() .when() .get() .then() .statusCode(200) .body("$", hasSize(1)) .body("isbn", hasItem("978-4798161488")) .body("title", hasItem("MySQL徹底入門 第4版 MySQL 8.0対応")) .body("price", hasItem(4180)); } @Test @Order(2) public void putBooks() { List<Book> books = List.of( Book.create("978-4621303252", "Effective Java 第3版", 4400), Book.create("978-4774189093", "Java本格入門 〜モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで", 3278), Book.create("978-4295010333", "いちばんやさしいJavaの教本 人気講師が教えるプログラミングの基礎", 2640) ); books.forEach(book -> { given() .contentType(ContentType.JSON) .body(book) .when() .put("/" + book.getIsbn()) .then() .statusCode(201) .header("Location", "/book/" + book.getIsbn()); }); given() .when() .get() .then() .statusCode(200) .body("$", hasSize(4)); } @Test @Order(3) public void findOne() { given() .when() .get("/978-4774189093") .then() .statusCode(200) .body("isbn", is("978-4774189093")) .body("title", is("Java本格入門 〜モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで")) .body("price", is(3278)); } @Test @Order(4) public void deleteBooks() { List<Book> books = List.of( Book.create("978-4621303252", "Effective Java 第3版", 4400), Book.create("978-4774189093", "Java本格入門 〜モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで", 3278), Book.create("978-4295010333", "いちばんやさしいJavaの教本 人気講師が教えるプログラミングの基礎", 2640) ); books.forEach(book -> { when() .delete("/" + book.getIsbn()) .then() .statusCode(200); }); given() .when() .get() .then() .statusCode(200) .body("$", hasSize(1)); } }
テスト前のデータベースの状態を確認。
mysql> use test; Database changed mysql> show tables; Empty set (0.01 sec)
では、テストを実行します。
$ mvn test
テスト実行時にマイグレーションが適用されていることが確認できます。
[INFO] Running org.littlewings.quarkus.flyway.BookResourceTest 2022-01-21 01:53:20,698 INFO [org.fly.cor.int.lic.VersionPrinter] (main) Flyway Community Edition 8.1.0 by Redgate 2022-01-21 01:53:20,706 INFO [org.fly.cor.int.dat.bas.BaseDatabaseType] (main) Database: jdbc:mysql://172.17.0.2:3306/test (MySQL 8.0) 2022-01-21 01:53:20,758 INFO [org.fly.cor.int.sch.JdbcTableSchemaHistory] (main) Creating Schema History table `test`.`flyway_schema_history` ... 2022-01-21 01:53:20,995 INFO [org.fly.cor.int.com.DbMigrate] (main) Current version of schema `test`: << Empty Schema >> 2022-01-21 01:53:21,040 INFO [org.fly.cor.int.com.DbMigrate] (main) Migrating schema `test` to version "1 - create book table" 2022-01-21 01:53:21,411 INFO [org.fly.cor.int.com.DbMigrate] (main) Migrating schema `test` to version "2 - create account table" 2022-01-21 01:53:21,539 INFO [org.fly.cor.int.com.DbMigrate] (main) Migrating schema `test` to version "99 - insert test data" 2022-01-21 01:53:21,573 INFO [org.fly.cor.int.com.DbMigrate] (main) Successfully applied 3 migrations to schema `test`, now at version v99 (execution time 00:00.594s)
テスト終了後、データベース側を確認。
mysql> show tables; +-----------------------+ | Tables_in_test | +-----------------------+ | account | | book | | flyway_schema_history | +-----------------------+ 3 rows in set (0.01 sec) mysql> select * from flyway_schema_history; +----------------+---------+----------------------+------+---------------------------------------------+------------+--------------+---------------------+----------------+---------+ | installed_rank | version | description | type | script | checksum | installed_by | installed_on | execution_time | success | +----------------+---------+----------------------+------+---------------------------------------------+------------+--------------+---------------------+----------------+---------+ | 1 | 1 | create book table | SQL | db/migration/V1__create_book_table.sql | 657681960 | testuser | 2022-01-20 16:53:21 | 332 | 1 | | 2 | 2 | create account table | SQL | db/migration/V2__create_account_table.sql | 1435889679 | testuser | 2022-01-20 16:53:21 | 85 | 1 | | 3 | 99 | insert test data | SQL | test/db/migration/V99__insert_test_data.sql | 905141387 | testuser | 2022-01-20 16:53:21 | 4 | 1 | +----------------+---------+----------------------+------+---------------------------------------------+------------+--------------+---------------------+----------------+---------+ 3 rows in set (0.00 sec)
2つのディレクトリのマイグレーションが適用されていることが確認できました。
まとめ
今回はFlywayをQuarkusに組み込んで(Flyway Extension)を使って試してみました。
簡単に使えて良いですね。Flyway自体は前に試していたので、そんなに困りませんでした。