Using Flyway
Flyway 是一个流行的数据库迁移工具,通常在 JVM 环境中使用。 Quarkus 提供了一流的支持来使用 Flyway,正如本指南中所解释的那样。
Setting up support for Flyway
正如 [developing-with-flyway] 部分中所示,要开始在项目中使用 Flyway,您只需:
-
将您的迁移添加到
src/main/resources/db/migration
文件夹,就像您通常对 Flyway 所做的那样 -
激活
migrate-at-start
选项以自动迁移架构,或注入Flyway
对象并按您通常的方式运行迁移
在构建文件中,添加以下依赖项:
-
the Flyway extension
-
您的 JDBC 驱动程序扩展 (
quarkus-jdbc-postgresql
、quarkus-jdbc-h2
、quarkus-jdbc-mariadb
、……) -
除非您使用的是内存数据库或文件数据库(例如 H2 或 SQLite),您需要添加一个与您正在使用的数据库相对应的 Flyway 模块依赖项。( for more details)
<!-- 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 Postgres 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 Postgres 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 的数据源配置。它可以针对默认数据源以及每个 named datasource 进行自定义。首先,您需要将数据源配置添加到 application.properties
文件中,以允许 Flyway 管理架构。此外,您可以使用以下属性自定义 Flyway 行为:
Unresolved include directive in modules/ROOT/pages/flyway.adoc - include::../../../target/quarkus-generated-doc/config/quarkus-flyway.adoc[]
Developing with 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://localhost: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 方法。
使用 |
@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 将自动重启应用程序。如果您希望在开发和测试新迁移脚本时利用这一优势,您将需要设置 |
Repairing the Flyway schema history table
不同的场景可能需要 repairing Flyway 架构历史表。其中一个场景是在不支持事务性 DDL 语句的数据库中迁移失败时。
在这种情况下, Flyway repair command 非常有用。在 Quarkus 中,可以通过设置 quarkus.flyway.repair-at-start=true
在迁移之前自动执行此操作,或者通过注入 Flyway
对象并调用 Flyway#repair()
手动执行此操作。
Multiple datasources
可以为多个数据源配置 Flyway。Flyway 属性的前缀与命名的数据源完全相同,例如:
quarkus.datasource.db-kind=h2
quarkus.datasource.username=username-default
quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/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://localhost/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://localhost/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 会使用默认设置,针对每个数据源进行设置。 |
Customizing 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
}
}
Using the Flyway object
如果你有兴趣直接使用 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 and Hibernate ORM
当将 Flyway 与 Hibernate ORM 结合使用时,可以使用 Dev UI 来生成初始化架构创建脚本。
你可以在 Hibernate ORM guide 中找到有关此功能的更多信息。
Flyway and Reactive datasources
Flyway 在内部依赖 JDBC 数据源,而响应式用例将依靠 reactive SQL clients,直接使用或通过 Hibernate Reactive 使用。这在 Quarkus 中不是问题,因为 a single configured datasource can be made available both through reactive clients and JDBC。
Flyway on Kubernetes
Sometimes, it’s helpful not to execute Flyway initialization on each application startup. One such example is when deploying
on Kubernetes, where it doesn’t make sense to execute Flyway on every single replica. Instead it’s desirable to execute itonce and then start the actual application without Flyway. To support this use case, when generating manifests for Kubernetesthe generated manifests contain a Kubernetes initialization Job
for Flyway.The Job
performs initialization and the actual Pod
, will starts once the Job
is successfully completed.
Disabling
此功能默认启用,可以使用以下内容进行全局禁用:
quarkus.kubernetes.init-task-defaults.enabled=false
或在 OpenShift 上:
quarkus.openshift.init-task-defaults.enabled=false
Using a custom image that controls waiting for the Job
若要更改默认`groundnuty/k8s-wait-for:no-root-v1.7` 的 wait-for
图像,可以使用:
quarkus.kubernetes.init-task-defaults.wait-for-container.image=my/wait-for-image:1.0
或在 OpenShift 上:
quarkus.openshift.init-task-defaults.wait-for-container.image=my/wait-for-image:1.0
Note: 在此上下文中,全局意味着 for all extensions that support init task externalization
.