Using 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-postgresqlquarkus-jdbc-h2quarkus-jdbc-mariadb、……)

  • 除非您使用的是内存数据库或文件数据库(例如 H2 或 SQLite),您需要添加一个与您正在使用的数据库相对应的 Flyway 模块依赖项。( for more details

pom.xml
<!-- 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>
build.gradle
// 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 方法。

使用 quarkus.flyway.migrate-at-start=true,就像上面示例中一样,Quarkus 将在 application startup 的一部分中执行 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 实际运行修改后的迁移。

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,只需确保将该数据源配置为 JDBCreactive。特别是,这涉及向 Quarkus 扩展添加 JDBC 驱动程序和响应式客户端的依赖项,例如 quarkus-jdbc-postgresql and quarkus-reactive-pg-client

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.