使用 Flyway
Flyway 是一个流行的数据库迁移工具,通常用于 JVM 环境中。
Quarkus 提供了对使用 Flyway 的一流支持,本指南将对此进行解释。
设置 Flyway 的支持
如 使用 Flyway 进行开发 部分所示,要开始在项目中使用 Flyway,您只需要
-
像通常使用 Flyway 一样,将迁移添加到
src/main/resources/db/migration
文件夹 -
激活
migrate-at-start
选项以自动迁移架构,或者注入Flyway
对象并像通常一样运行迁移
在您的构建文件中,添加以下依赖项
-
Flyway 扩展
-
您的 JDBC 驱动程序扩展(
quarkus-jdbc-postgresql
、quarkus-jdbc-h2
、quarkus-jdbc-mariadb
,...) -
除非您使用的是内存或文件数据库(例如 H2 或 SQLite),否则您需要添加与您正在使用的数据库对应的 flyway 模块依赖项。(更多详细信息)
<!-- Flyway specific dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-flyway</artifactId>
</dependency>
<!-- JDBC driver dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
<!-- Flyway SQL Server specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-sqlserver</artifactId>
</dependency>
<!-- Flyway MariaDB/MySQL specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<!-- Flyway Oracle specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-oracle</artifactId>
</dependency>
<!-- Flyway PostgreSQL specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-postgresql</artifactId>
</dependency>
<!-- Flyway DB2 specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-db2</artifactId>
</dependency>
<!-- Derby specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-derby</artifactId>
</dependency>
<!-- HSQLDB specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-hsqldb</artifactId>
</dependency>
<!-- Informix specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-informix</artifactId>
</dependency>
<!-- Redshift specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-redshift</artifactId>
</dependency>
<!-- Saphana specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-saphana</artifactId>
</dependency>
<!-- Snowflake specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-snowflake</artifactId>
</dependency>
<!-- Sybasease specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-sybasease</artifactId>
</dependency>
<!-- Firebird specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-firebird</artifactId>
</dependency>
<!-- BigQuery specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-gcp-bigquery</artifactId>
</dependency>
<!-- Spanner specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-gcp-spanner</artifactId>
</dependency>
<!-- Singlestore specific dependencies -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-singlestore</artifactId>
</dependency>
// Flyway specific dependencies
implementation("io.quarkus:quarkus-flyway")
// JDBC driver dependencies
implementation("io.quarkus:quarkus-jdbc-postgresql")
// Flyway SQL Server specific dependencies
implementation("org.flywaydb:flyway-sqlserver")
// Flyway MariaDB/MySQL specific dependencies
implementation("org.flywaydb:flyway-mysql")
// Flyway Oracle specific dependencies
implementation("org.flywaydb:flyway-database-oracle")
// Flyway PostgreSQL specific dependencies
implementation("org.flywaydb:flyway-database-postgresql")
// Flyway DB2 specific dependencies
implementation("org.flywaydb:flyway-database-db2")
// Flyway Derby specific dependencies
implementation("org.flywaydb:flyway-database-derby")
// HSQLDB specific dependencies
implementation("org.flywaydb:flyway-database-hsqldb")
// Informix specific dependencies
implementation("org.flywaydb:flyway-database-informix")
// Redshift specific dependencies
implementation("org.flywaydb:flyway-database-redshift")
// Saphana specific dependencies
implementation("org.flywaydb:flyway-database-saphana")
// Snowflake specific dependencies
implementation("org.flywaydb:flyway-database-snowflake")
// Sybasease specific dependencies
implementation("org.flywaydb:flyway-database-sybasease")
// Firebird specific dependencies
implementation("org.flywaydb:flyway-firebird")
// BigQuery specific dependencies
implementation("org.flywaydb:flyway-gcp-bigquery")
// Spanner specific dependencies
implementation("org.flywaydb:flyway-gcp-spanner")
// Singlestore specific dependencies
implementation("org.flywaydb:flyway-singlestore:10.15.0")
Flyway 支持依赖于 Quarkus 数据源配置。可以为默认数据源以及每个命名数据源自定义它。首先,您需要在 application.properties
文件中添加数据源配置,以便 Flyway 管理架构。此外,您可以使用以下属性自定义 Flyway 的行为
构建时固定的配置属性 - 所有其他配置属性都可以在运行时覆盖
配置属性 |
类型 |
默认 |
---|---|---|
Flyway 是否在构建期间启用。 如果 Flyway 被禁用,则不会创建 Flyway bean,并且 Flyway 将不可用。 环境变量: 显示更多 |
布尔值 |
|
类型 |
默认 |
|
要递归扫描迁移的以逗号分隔的位置列表。位置类型由其前缀确定。 没有前缀的位置或以 classpath: 开头的位置指向类路径上的包,并且可能包含 SQL 和基于 Java 的迁移。 以 filesystem: 开头的位置指向文件系统上的目录,可能只包含 SQL 迁移,并且只递归扫描非隐藏目录。 环境变量: 显示更多 |
字符串列表 |
|
以逗号分隔的回调实现类的完全限定名称列表,用于挂钩到 Flyway 生命周期。 环境变量: 显示更多 |
字符串列表 |
|
用于在运行时激活/停用特定数据源的 Flyway 的标志。 环境变量: 显示更多 |
布尔值 |
|
尝试连接到数据库时的最大重试次数。 每次尝试失败后,Flyway 将等待最多配置的 环境变量: 显示更多 |
整数 |
|
尝试连接到数据库时,重试之间的最大时间。 这将限制连接重试之间的间隔,使其不超过提供的值。 环境变量: 显示更多 |
|
|
设置 Flyway 管理的默认架构。此架构名称区分大小写。如果未指定,但指定了架构,则 Flyway 使用该列表中的第一个架构。如果这也未指定,则 Flyway 使用数据库连接的默认架构。 后果
环境变量: 显示更多 |
字符串 |
|
Flyway 用于连接到数据库的 JDBC URL。如果未指定,则回退到数据源 URL。 环境变量: 显示更多 |
字符串 |
|
Flyway 用于连接到数据库的用户名。如果未配置特定的 JDBC URL,则如果未指定,则回退到数据源用户名。 环境变量: 显示更多 |
字符串 |
|
Flyway 用于连接到数据库的密码。如果未配置特定的 JDBC URL,则如果未指定,则回退到数据源密码。 环境变量: 显示更多 |
字符串 |
|
Flyway 管理的区分大小写的架构的逗号分隔列表。列表中的第一个架构将在迁移期间自动设置为默认架构。它也将是包含架构历史记录表的架构。 环境变量: 显示更多 |
字符串列表 |
|
Flyway 的架构历史记录表的名称。默认情况下(单架构模式),架构历史记录表放置在数据源提供的连接的默认架构中。当设置了 flyway.schemas 属性(多架构模式)时,架构历史记录表放置在列表的第一个架构中。 环境变量: 显示更多 |
字符串 |
|
版本化 SQL 迁移的文件名前缀。版本化 SQL 迁移具有以下文件名结构:prefixVERSIONseparatorDESCRIPTIONsuffix,使用默认值时转换为 V1.1__My_description.sql 环境变量: 显示更多 |
字符串 |
|
可重复 SQL 迁移的文件名前缀。可重复 SQL 迁移具有以下文件名结构:prefixSeparatorDESCRIPTIONsuffix,使用默认值时转换为 R__My_description.sql 环境变量: 显示更多 |
字符串 |
|
如果应用程序启动时自动执行 Flyway clean 命令,则为 true;否则为 false。 环境变量: 显示更多 |
布尔值 |
|
如果阻止 Flyway clean 操作,则为 true;否则为 false。 环境变量: 显示更多 |
布尔值 |
|
如果应用程序启动时自动执行 Flyway,则为 true;否则为 false。 环境变量: 显示更多 |
布尔值 |
|
如果应用程序启动时执行 Flyway repair 命令,则为 true;否则为 false。 环境变量: 显示更多 |
布尔值 |
|
如果应用程序启动时执行 Flyway validate 命令,则为 true;否则为 false。 环境变量: 显示更多 |
布尔值 |
|
如果在启动时发生验证错误,则自动执行 Flyway clean 命令,否则为 false。 环境变量: 显示更多 |
布尔值 |
|
如果要在迁移之前执行 Flyway baseline,则为 true。如果在当前架构中存在 flyway_schema_history 表,或者当前架构为空,则忽略此标志。请注意,这不会自动调用迁移,您必须启用 baselineAtStart 或以编程方式调用 flyway.migrate()。 环境变量: 显示更多 |
布尔值 |
|
如果应用程序启动时自动执行 Flyway baseline,则为 true。如果在当前架构中存在 flyway_schema_history 表,则忽略此标志。即使当前架构为空,这也可以工作。 环境变量: 显示更多 |
布尔值 |
|
初始基线版本。 环境变量: 显示更多 |
字符串 |
|
执行 baseline 时用于标记现有架构的描述。 环境变量: 显示更多 |
字符串 |
|
是否在执行迁移时自动调用 validate。 环境变量: 显示更多 |
布尔值 |
|
允许“乱序”运行迁移。 环境变量: 显示更多 |
布尔值 |
|
读取历史记录表时忽略缺少的迁移。当设置为 true 时,将忽略历史记录表中存在的旧版本迁移,但在配置的位置中不存在这些迁移(并记录为警告),当为 false 时(默认),验证步骤将失败。 环境变量: 显示更多 |
布尔值 |
|
读取历史记录表时忽略将来的迁移。当设置为 true 时,将忽略历史记录表中存在的新版本迁移,但在配置的位置中不存在这些迁移(并记录为警告),当为 false 时(默认),验证步骤将失败。 环境变量: 显示更多 |
布尔值 |
|
设置要在 SQL 迁移脚本中替换的占位符。 环境变量: 显示更多 |
Map<String,String> |
|
Flyway 是否应尝试创建 schemas 属性中指定的架构 环境变量: 显示更多 |
布尔值 |
|
每个占位符的前缀(默认值:${ ) 环境变量: 显示更多 |
字符串 |
|
每个占位符的后缀(默认值:} ) 环境变量: 显示更多 |
字符串 |
|
在打开新的数据库连接后立即运行的 SQL 语句,用于初始化连接。 环境变量: 显示更多 |
字符串 |
|
是否验证脚本不遵守正确命名约定的迁移和回调。故障对于检查是否已更正迁移前缀中的大小写敏感性等错误非常有用。 环境变量: 显示更多 |
布尔值 |
|
根据给定的模式列表(有关详细信息,请参阅 https://flywaydb.org/documentation/configuration/parameters/ignoreMigrationPatterns)在验证和修复期间忽略迁移。设置此配置后,将忽略 ignoreFutureMigrations 和 ignoreMissingMigrations 设置。模式以逗号分隔。 环境变量: 显示更多 |
字符串列表 |
关于 Duration 格式
要编写持续时间值,请使用标准 您还可以使用简化的格式,以数字开头
在其他情况下,简化格式将被转换为
|
使用 Flyway 进行开发
以下是 application.properties
文件的示例
# configure your datasource
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=sarah
quarkus.datasource.password=connor
quarkus.datasource.jdbc.url=jdbc:postgresql://:5432/mydatabase
# Run Flyway migrations automatically
quarkus.flyway.migrate-at-start=true
# More Flyway configuration options
# quarkus.flyway.baseline-on-migrate=true
# quarkus.flyway.baseline-version=1.0.0
# quarkus.flyway.baseline-description=Initial version
# quarkus.flyway.connect-retries=10
# quarkus.flyway.schemas=TEST_SCHEMA
# quarkus.flyway.table=flyway_quarkus_history
# quarkus.flyway.locations=db/location1,db/location2
# quarkus.flyway.sql-migration-prefix=X
# quarkus.flyway.repeatable-sql-migration-prefix=K
按照 Flyway 命名约定将 SQL 迁移添加到默认文件夹:src/main/resources/db/migration/V1.0.0__Quarkus.sql
CREATE TABLE quarkus
(
id INT,
name VARCHAR(20)
);
INSERT INTO quarkus(id, name)
VALUES (1, 'QUARKED');
现在您可以启动应用程序,Quarkus 将根据您的配置运行 Flyway 的 migrate 方法。
使用 quarkus.flyway.migrate-at-start=true ,如上面的示例所示,Quarkus 将执行 Flyway 迁移作为应用程序启动的一部分。 |
@ApplicationScoped
public class MigrationService {
// You can Inject the object if you want to use it manually
@Inject
Flyway flyway; (1)
public void checkMigration() {
// This will print 1.0.0
System.out.println(flyway.info().current().getVersion().toString());
}
}
1 | 如果您想直接使用 Flyway 对象,请注入它 |
在开发模式下,如果任何现有迁移脚本被修改,Quarkus 将自动重新启动应用程序。如果您想在开发和测试新迁移脚本时利用这一点,您需要设置 %dev.quarkus.flyway.clean-at-start=true ,以便 Flyway 实际运行修改后的迁移。 |
修复 Flyway 架构历史记录表
有不同的情况可能需要修复 Flyway 架构历史记录表。一种这样的情况是在不支持事务性 DDL 语句的数据库中迁移失败时。
在这种情况下,Flyway repair 命令会派上用场。在 Quarkus 中,可以通过设置 quarkus.flyway.repair-at-start=true
在迁移之前自动执行此命令,也可以通过注入 Flyway
对象并调用 Flyway#repair()
手动执行。
多个数据源
可以为多个数据源配置 Flyway。Flyway 属性的前缀与命名数据源完全相同,例如
quarkus.datasource.db-kind=h2
quarkus.datasource.username=username-default
quarkus.datasource.jdbc.url=jdbc:h2:tcp:///mem:default
quarkus.datasource.jdbc.max-size=13
quarkus.datasource.users.db-kind=h2
quarkus.datasource.users.username=username1
quarkus.datasource.users.jdbc.url=jdbc:h2:tcp:///mem:users
quarkus.datasource.users.jdbc.max-size=11
quarkus.datasource.inventory.db-kind=h2
quarkus.datasource.inventory.username=username2
quarkus.datasource.inventory.jdbc.url=jdbc:h2:tcp:///mem:inventory
quarkus.datasource.inventory.jdbc.max-size=12
# Flyway configuration for the default datasource
quarkus.flyway.schemas=DEFAULT_TEST_SCHEMA
quarkus.flyway.locations=db/default/location1,db/default/location2
quarkus.flyway.migrate-at-start=true
# Flyway configuration for the "users" datasource
quarkus.flyway.users.schemas=USERS_TEST_SCHEMA
quarkus.flyway.users.locations=db/users/location1,db/users/location2
quarkus.flyway.users.migrate-at-start=true
# Flyway configuration for the "inventory" datasource
quarkus.flyway.inventory.schemas=INVENTORY_TEST_SCHEMA
quarkus.flyway.inventory.locations=db/inventory/location1,db/inventory/location2
quarkus.flyway.inventory.migrate-at-start=true
请注意,密钥中有一个额外的位。语法如下:quarkus.flyway.[optional name.][datasource property]
。
如果没有配置,则使用默认设置为每个数据源设置 Flyway。 |
自定义 Flyway
如果除了 Quarkus 提供的配置选项之外还需要配置 Flyway,则 io.quarkus.flyway.FlywayConfigurationCustomizer
类会派上用场。
要自定义默认数据源的 Flyway,只需添加一个 bean,如下所示
@Singleton
public static class MyCustomizer implements FlywayConfigurationCustomizer {
@Override
public void customize(FluentConfiguration configuration) {
// do something with configuration
}
}
当使用命名数据源时,可以使用 @FlywayDataSource
注解来指定自定义程序应用到的数据源。例如,如果有多个数据源,其中一个名为 users
,并且只需要为该数据源自定义 Flyway,则可以使用以下代码
@Singleton
@FlywayDataSource("users")
public static class UsersCustomizer implements FlywayConfigurationCustomizer {
@Override
public void customize(FluentConfiguration configuration) {
// do something with configuration
}
}
使用 Flyway 对象
如果您有兴趣直接使用 Flyway
对象,您可以按如下方式注入它
@ApplicationScoped
public class MigrationService {
// You can Inject the object if you want to use it manually
@Inject
Flyway flyway; (1)
@Inject
@FlywayDataSource("inventory") (2)
Flyway flywayForInventory;
@Inject
@Named("flyway_users") (3)
Flyway flywayForUsers;
public void checkMigration() {
// Use the flyway instance manually
flyway.clean(); (4)
flyway.migrate();
// This will print 1.0.0
System.out.println(flyway.info().current().getVersion().toString());
}
}
1 | 如果您想直接使用 Flyway 对象,请注入它 |
2 | 使用 Quarkus FlywayDataSource 限定符为命名数据源注入 Flyway |
3 | 为命名数据源注入 Flyway |
4 | 直接使用 Flyway 实例 |
Flyway 和 Hibernate ORM
将 Flyway 与 Hibernate ORM 一起使用时,您可以使用 Dev UI 生成初始架构创建脚本。
您可以在Hibernate ORM 指南中找到有关此功能的更多信息。
Flyway 和 Reactive 数据源
Flyway 在内部依赖于 JDBC 数据源,而 Reactive 用例将依赖于Reactive SQL 客户端,无论是直接还是通过Hibernate Reactive。这在 Quarkus 中不是问题,因为可以通过 Reactive 客户端和 JDBC 同时提供单个配置的数据源。
Kubernetes 上的 Flyway
有时,在每个应用程序启动时不执行 Flyway 初始化会很有帮助。一个这样的例子是部署
在 Kubernetes 上,在每个副本上执行 Flyway 没有意义。相反,最好执行一次,然后在没有 Flyway 的情况下启动实际应用程序。为了支持此用例,当为 Kubernetes 生成清单时,生成的清单包含用于 Flyway 的 Kubernetes 初始化 Job
。Job
执行初始化,实际的 Pod
将在 Job
成功完成后启动。