1. 序章

Flywayライブラリを使用すると、SQLソースコードとして保存されている変更を追跡することでデータベースをバージョン管理できます。 変更の各セットは移行と呼ばれます。

migrate clean、info、validate、 baseline repair を含む一連のコマンドを使用して、個々の移行がデータベースに順番に適用されます。 。 これらは、ターゲットデータベースの現在のバージョンに従って制御された方法で適用されます。

通常、ほとんどのユースケースをカバーするには移行で十分ですが、コールバックに適したシナリオがいくつかあります。

この記事では、Flywayコールバックを使用して、提供されるさまざまなコマンドのライフサイクルにフックします。

2. ユースケースシナリオ

コールバックによって提供される一種の柔軟性を必要とする非常に特定の要件がある場合があります。 考えられるユースケースは次のとおりです。

  • マテリアライズド・ビューの再構築– マテリアライズド・ビューのベース・テーブルに影響を与える移行を適用するたびに、マテリアライズド・ビューを再構築したい場合があります。 SQLコールバックは、このタイプのロジックを実行するのに適しています
  • キャッシュのフラッシュ– おそらく、キャッシュされたデータを変更する移行があります。 キャッシュをフラッシュするへのコールバックを使用して、アプリケーションがデータベースから新しいデータをプルするようにすることができます
  • 外部システムの呼び出し– コールバックを使用して、任意のテクノロジーを使用して外部システムを呼び出すことができます。 たとえば、イベントを公開したり、メールを送信したり、サーバーの再起動をトリガーしたりすることができます。

3. サポートされているコールバック

使用可能なFlywayコマンドごとに、対応するbeforeおよびafterコールバックイベントがあります。 これらのコマンドの詳細については、メインのFlywayの記事または公式ドキュメントを参照してください。

  • BEFORE_イベントは、操作が実行される前に発生します。
  • AFTER_イベントは、操作が成功した後に発生します。 これらのafterイベントには、さらに詳細なイベントがいくつかあります。
    • 操作が失敗した後、同等のERRORが発生します。
    • OPERATION_FINISHイベントは、操作が終了した後に発生します。
  • migrateおよびundoにも、個々の移行ごとに発生する_EACHイベントがあります。 migrate およびundoコマンドは、これらのコマンドを実行すると多くの移行が実行されることが多いため、これらの追加のコールバックを備えています。

コールバックイベントの完全なリストは、Eventクラスにあります。

たとえば、cleanコマンドのコールバックイベントはBEFORE_CLEANおよびAFTER_CLEANです。 Flywayは、cleanコマンドの実行の直前と直後にそれらを起動します。

はじめに説明したことを思い出して、使用可能なコマンドは次のとおりです。

Flywayの作成者は、これらの追加のフックを提供して、Flywayが機能する最高レベルの粒度、つまり個々の移行でカスタムコールバックロジックを制御できるようにしました。

4. 依存関係

コールバックが実際にどのように機能するかを確認するために、簡単な例を見てみましょう。 pom.xml でflyway-coreを依存関係として宣言することで、この例を開始できます。

<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
    <version>8.0.0</version>
</dependency>

flyway-core の最新バージョンは、 MavenCentralにあります。

5. コールバック

Flywayを使用すると、JavaまたはSQLという2つの異なるアプローチを使用してコールバックを作成できます。 前者が最も柔軟なものです。 これにより、任意のコードを実行する自由が得られます。

後者を使用すると、データベースを直接操作できます。

5.1. Javaコールバック

Java APIコントラクトは、Callbackインターフェースで定義されています。

最も単純なケースでは、カスタムコールバックを作成するには、 ExampleFlywayCallback:のように、Callbackインターフェイスを実装する必要があります。

public class ExampleFlywayCallback implements Callback {

    private final Log log = LogFactory.getLog(getClass());

    @Override
    public boolean supports(Event event, Context context) {
        return event == Event.AFTER_EACH_MIGRATE;
    }

    @Override
    public boolean canHandleInTransaction(Event event, Context context) {
        return true;
    }

    @Override
    public void handle(Event event, Context context) {
        if (event == Event.AFTER_EACH_MIGRATE) {
            log.info("> afterEachMigrate");
        }
    }

    @Override
    public String getCallbackName() {
        return ExampleFlywayCallback.class.getSimpleName();
    }
}

5.2. SQLコールバック

SQLコールバックコントラクトは、ロケーションとして構成されたディレクトリに含まれる特定の名前のファイルを使用して定義されます。 Flywayは、構成されたロケーションでSQLコールバックファイルを検索します。それに応じてそれらを実行します。

例として、locationとして構成されたディレクトリ内のbeforeEachMigrate.sqlという名前のファイルは、migrateコマンドの実行中に各移行スクリプトの前に実行されます。

6. 構成と実行

次の例では、Javaコールバックを構成し、2つのSQLスクリプトの場所を指定します。1つは移行を含み、もう1つはSQLコールバックを含みます。

移行とSQLコールバック用に別々の場所を構成する必要はありませんが、この例では、これらを別々に保つ方法を示すために、このように設定しました。

@Test
public void migrateWithSqlAndJavaCallbacks() {
    Flyway flyway = Flyway.configure()
      .dataSource(dataSource)
      .locations("db/migration", "db/callbacks")
      .callbacks(new ExampleFlywayCallback())
      .load();
    flyway.migrate();
}

JavaとSQLの両方でbeforeEachMigrateを定義する場合、Javaコールバックが最初に実行され、直後にSQLコールバックが実行されることを知っておくと役立ちます。

これは、上記のテストからの出力で確認できます。

21:50:45.677 [main] INFO  c.b.f.FlywayApplicationUnitTest - > migrateWithSqlAndJavaCallbacks
21:50:45.848 [main] INFO  o.f.c.i.license.VersionPrinter - Flyway Community Edition 8.0.0 by Redgate
21:50:45.849 [main] INFO  o.f.c.i.d.base.BaseDatabaseType - Database: jdbc:h2:mem:DATABASE (H2 1.4)
21:50:45.938 [main] INFO  o.f.core.internal.command.DbValidate - Successfully validated 2 migrations (execution time 00:00.021s)
21:50:45.951 [main] INFO  o.f.c.i.s.JdbcTableSchemaHistory - Creating Schema History table "PUBLIC"."flyway_schema_history" ...
21:50:46.003 [main] INFO  o.f.c.i.c.SqlScriptCallbackFactory - Executing SQL callback: beforeMigrate - 
21:50:46.015 [main] INFO  o.f.core.internal.command.DbMigrate - Current version of schema "PUBLIC": << Empty Schema >>
21:50:46.023 [main] INFO  o.f.c.i.c.SqlScriptCallbackFactory - Executing SQL callback: beforeEachMigrate - 
21:50:46.024 [main] INFO  o.f.core.internal.command.DbMigrate - Migrating schema "PUBLIC" to version "1.0 - add table one"
21:50:46.025 [main] INFO  c.b.f.ExampleFlywayCallback - > afterEachMigrate
21:50:46.046 [main] INFO  o.f.c.i.c.SqlScriptCallbackFactory - Executing SQL callback: beforeEachMigrate - 
21:50:46.046 [main] INFO  o.f.core.internal.command.DbMigrate - Migrating schema "PUBLIC" to version "1.1 - add table two"
21:50:46.047 [main] INFO  c.b.f.ExampleFlywayCallback - > afterEachMigrate
21:50:46.067 [main] INFO  o.f.core.internal.command.DbMigrate - Successfully applied 2 migrations to schema "PUBLIC", now at version v1.1 (execution time 00:00.060s)

7. 結論

この記事では、FlywayコールバックメカニズムをJavaとSQLの両方で使用する方法について説明しました。 考えられるユースケースを検討し、例を詳しく説明しました。

いつものように、すべてのソースコードはGitHubにあります。