Flyway 回调简介
1. 简介
Flyway 库允许我们通过跟踪存储为 SQL 源代码的更改来对数据库进行版本控制。每组更改称为一次migration。
使用一组命令(包括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命令执行前后立即触发它们。
回顾我们在介绍中讨论的内容,可用的命令有:migrate、clean、info、validate、 baseline和repair。
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)