Spring R2dbc Flyway

2025/03/23

1. 简介

在本教程中,我们将使用Flyway探索Spring R2DBC迁移,Flyway是一种常用于数据库迁移的开源工具。虽然在撰写本文时它还没有对R2DBC的原生支持,但我们将研究在应用程序启动期间迁移表和数据的替代方法。

2. 基本Spring R2DBC应用程序

在本文中,我们将使用一个简单的Spring R2DBC应用程序,并使用Flyway进行迁移来创建表并将数据插入PostgreSQL数据库。

2.1 R2DBC

R2DBC代表Reactive Relational Database,它基于Reactive Streams规范,该规范提供了用于与SQL数据库交互的完全响应式非阻塞API。然而,尽管它有很多好处,但Flyway等一些工具目前不支持R2DBC,这意味着使用Flyway进行迁移需要JDBC(阻塞)驱动程序。

数据库迁移允许应用程序在部署新版本时在启动时升级数据库模式,这些迁移是使数据库结构与应用程序需求相匹配所必需的。由于这些更改是在应用程序启动之前必须进行的,因此同步阻塞迁移是可以接受的。

2.2 依赖

我们需要一些依赖来使R2DBC应用程序与Flyway兼容。

我们需要spring-boot-starter-data-r2dbc依赖,它提供核心Spring R2DBC数据抽象和PostgreSQL R2DBC驱动程序:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>r2dbc-postgresql</artifactId>
    <version>1.0.5.RELEASE</version>
</dependency>

为了配置数据库迁移,我们需要Flyway

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

由于Flyway尚不支持R2DBC驱动程序,因此我们还需要添加PostgreSQL的标准JDBC驱动程序

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.7.3</version>
</dependency>

3. Spring R2DBC应用程序上的Flyway迁移

让我们看看Flyway迁移和示例脚本所需的配置。

3.1 Spring R2DBC和Flyway的配置

由于Flyway不能与R2DBC一起使用,我们需要使用初始化方法migration()创建Flyway Bean,这会提示Spring在创建Bean后立即运行我们的迁移

@Configuration
@EnableConfigurationProperties({ R2dbcProperties.class, FlywayProperties.class })
class DatabaseConfig {
    @Bean(initMethod = "migrate")
    public Flyway flyway(FlywayProperties flywayProperties, R2dbcProperties r2dbcProperties) {
        return Flyway.configure()
                .dataSource(
                        flywayProperties.getUrl(),
                        r2dbcProperties.getUsername(),
                        r2dbcProperties.getPassword()
                )
                .locations(flywayProperties.getLocations()
                        .stream()
                        .toArray(String[]::new))
                .baselineOnMigrate(true)
                .load();
    }
}

我们可以通过将R2DBC属性与一些特定于Flyway的覆盖合并来将Flyway指向我们的数据库,特别是URL,它必须是JDBC连接URL和Flyway将从中运行迁移的位置

在这个特定的例子中,Spring能够根据类路径中的依赖自动配置Postgresql R2DBC,但值得注意的是,R2DBC也为其他SQL数据库驱动程序提供支持。由于我们的应用程序中有R2DBC Starter,我们只需要为Spring R2DBC设置适当的属性,而不需要额外的配置。

让我们看一个R2DBC PostgreSQL和Flyway设置的属性文件示例,其中包含JDBC驱动程序所需的数据库URL:

spring:
    r2dbc:
        username: local
        password: local
        url: r2dbc:postgresql://localhost:8082/flyway-test-db
    flyway:
        url: jdbc:postgresql://localhost:8082/flyway-test-db
        locations: classpath:db/postgres/migration

虽然目录的默认位置是db/migration,但上述配置指定我们的迁移脚本位于db/postgres/migration目录中。

R2DBC URL格式包括:

  • jdbc/r2dbc:连接策略
  • postgresql:数据库类型
  • localhost:8082:PostgreSQLDB主机
  • flyway-test-db:数据库名称

3.2 迁移脚本

让我们创建迁移脚本,创建两个表(department和student),并在department表中插入一些数据。

我们的第一个脚本将创建department和student表,我们将其命名为V1_1__create_tables.sql,遵循文件命名约定,以便Flyway可以将其识别为第一个要执行的脚本。Flyway会跟踪它运行过的所有脚本,因此它只会运行每个脚本一次:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE TABLE IF NOT EXISTS department
(
    ID uuid PRIMARY KEY UNIQUE DEFAULT uuid_generate_v4(),
    NAME varchar(255)
);

CREATE TABLE IF NOT EXISTS student
(
    ID uuid PRIMARY KEY UNIQUE DEFAULT uuid_generate_v4(),
    FIRST_NAME varchar(255),
    LAST_NAME varchar(255),
    DATE_OF_BIRTH DATE NOT NULL,
    DEPARTMENT uuid NOT NULL CONSTRAINT student_foreign_key1 REFERENCES department (ID)
);

我们的下一个脚本将向表中插入一些数据,我们将其命名为V1_2__insert_department.sql,以便它第二次运行:

insert into department(NAME) values ('Computer Science');
insert into department(NAME) values ('Biomedical');

3.3 测试Spring R2DBC迁移

让我们做一个快速测试来验证设置。

首先,让我们编写一个用于启动PostgreSQL的示例docker-compose.yml:

version: '3.9'
networks:
    obref:
services:
    postgres_db_service:
        container_name: postgres_db_service
        image: postgres:11
        ports:
            - "8082:5432"
        hostname:   postgres_db_service
        environment:
            - POSTGRES_PASSWORD=local
            - POSTGRES_USER=local
            - POSTGRES_DB=flyway-test-db

第一次启动应用程序时,我们应该看到确认正在应用迁移的日志:

INFO 95740 --- [  restartedMain] o.f.c.internal.license.VersionPrinter    : Flyway Community Edition 9.14.1 by Redgate
INFO 95740 --- [  restartedMain] o.f.c.internal.license.VersionPrinter    : See what's new here: https://flywaydb.org/documentation/learnmore/releaseNotes#9.14.1
INFO 95740 --- [  restartedMain] o.f.c.internal.license.VersionPrinter    : 
INFO 95740 --- [  restartedMain] o.f.c.i.database.base.BaseDatabaseType   : Database: jdbc:postgresql://localhost:8082/flyway-test-db (PostgreSQL 11.16)
INFO 95740 --- [  restartedMain] o.f.core.internal.command.DbValidate     : Successfully validated 2 migrations (execution time 00:00.007s)
INFO 95740 --- [  restartedMain] o.f.c.i.s.JdbcTableSchemaHistory         : Creating Schema History table "public"."flyway_schema_history" ...
INFO 95740 --- [  restartedMain] o.f.core.internal.command.DbMigrate      : Current version of schema "public": << Empty Schema >>
INFO 95740 --- [  restartedMain] o.f.core.internal.command.DbMigrate      : Migrating schema "public" to version "1.1 - create tables"
INFO 95740 --- [  restartedMain] o.f.core.internal.command.DbMigrate      : Migrating schema "public" to version "1.2 - insert department"
INFO 95740 --- [  restartedMain] o.f.core.internal.command.DbMigrate      : Successfully applied 2 migrations to schema "public", now at version v1.2 (execution time 00:00.045s)
INFO 95740 --- [  restartedMain] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port 8080
INFO 95740 --- [  restartedMain] c.t.t.e.r.f.SpringWebfluxFlywayApplication : Started SpringWebfluxFlywayApplication in 1.895 seconds (JVM running for 2.28)

从以上日志我们可以看到,迁移脚本按照预期的顺序应用。

如果flyway_schema_history表不可用,则Flyway会创建该表并存储迁移状态的详细信息。脚本完成后,我们可以从该表中查看有关迁移的详细信息,包括文件的名称和执行时间。

4. 总结

在本文中,我们创建了一个基本的Spring R2DBC应用程序,并探索了使用Flyway为使用R2DBC的应用程序迁移数据的方法之一。我们还采用了一些策略来验证Flyway是否按预期应用了我们的迁移。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章