Contents

Flyway 回调简介

1. 简介

Flyway 库允许我们通过跟踪存储为 SQL 源代码的更改来对数据库进行版本控制。每组更改称为一次migration

使用一组命令(包括migrateclean 、 info 、 validate 、 baselinerepair )将单个迁移按顺序应用于数据库。它们根据目标数据库的当前版本以受控方式应用。

虽然迁移通常足以涵盖大多数用例,但有许多场景非常适合回调。

在本文中,我们将使用 Flyway 回调来挂钩它提供的各种命令的生命周期。

2. 用例场景

我们可能有一个非常具体的要求,需要回调提供的那种灵活性。以下是一些可能的用例:

  • **重建物化视图——我们可能希望在应用影响这些视图的基表的迁移时重建物化视图。**SQL 回调非常适合执行这种类型的逻辑
  • 刷新缓存——也许我们有一个修改恰好被缓存的数据的迁移。我们可以使用回调来刷新缓存,以确保我们的应用程序从数据库中提取新数据
  • **调用外部系统——使用回调,我们可以使用任意技术调用外部系统。**例如,我们可能想要发布事件、发送电子邮件或触发服务器重启

3. 支持的回调

每个可用的 Flyway 命令都有相应的*before after *回调事件。有关这些命令的更多信息,请参阅我们的 Flyway 文章官方文档

  • BEFORE_ 事件在操作执行之前被触发。
  • 操作成功后触发 AFTER_ 事件。这些after的事件还有一些更细化的事件:
    • 操作失败后会触发 ERROR 等效项。
    • 操作完成后会触发 OPERATION_FINISH 事件。
  • migrateundo也有 _EACH 事件,该事件会为每个单独的迁移触发。migrate和 undo 命令具有这些额外的回调,因为运行这些命令通常会导致执行许多迁移。

回调事件的完整列表可以在Event 类中找到。

例如,clean命令的回调事件是BEFORE_CLEANAFTER_CLEANFlyway 在clean命令执行前后立即触发它们。

回顾我们在介绍中讨论的内容,可用的命令有:migrateclean、info、validate、 baselinerepair

Flyway 的作者提供了这些额外的钩子,使我们能够在 Flyway 使用的最高粒度级别(即单独的迁移)上控制自定义回调逻辑。

4. 依赖

要了解回调在实践中是如何工作的,让我们通过一个简单的示例进行操作。我们可以通过在pom.xml中将 flyway-core 声明为依赖项来开始我们的示例:

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

我们可以在Maven Central 上找到flyway-core的最新版本。

5. 回调

Flyway 使我们能够使用两种不同的方法(Java 或 SQL)创建回调。前者是最灵活的。它为我们提供了执行任意代码的自由。

后者让我们直接与数据库交互。

5.1.Java 回调

Java API 契约在Callback接口中定义。

在最简单的情况下,要创建自定义回调,我们需要实现Callback接口,如ExampleFlywayCallback 中所示:

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 回调契约是通过使用配置为locations的目录中包含的具有特定名称的文件来定义的。**Flyway 将在其配置locations中查找 SQL 回调文件并相应地执行它们。

例如,在配置为locations的目录中名为beforeEachMigrate.sql的文件将在执行migrate命令期间在每个迁移脚本之前运行。

6.配置和执行

在以下示例中,我们配置 Java 回调并指定两个 SQL 脚本位置:一个包含我们的迁移,另一个包含 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)