简体   繁体   English

使用 R2DBC 进行数据库迁移

[英]Database migrations with R2DBC

I am new to R2DBC ( https://r2dbc.io/ ).我是 R2DBC ( https://r2dbc.io/ ) 的新手。 I would like to know whether r2dbc's ecosystem has a database migration tool/framework.我想知道r2dbc的生态系统是否有数据库迁移工具/框架。

It seems Liquibase & Flyway depend on JDBC.似乎 Liquibase & Flyway 依赖于 JDBC。 Is there a plan for allowing those frameworks to support a r2dbc driver?是否有计划允许这些框架支持 r2dbc 驱动程序?

Any input or feedback welcome.欢迎任何输入或反馈。

Steve's answer is correct hat R2DBC is primarily about interaction with the actual data. Steve 的回答是正确的,因为 R2DBC 主要是关于与实际数据的交互。 I'd like to add a different perspective.我想补充一个不同的观点。

It's true that a reactive API does not provide any improvement during migrations.确实,响应式 API 在迁移期间不会提供任何改进。 In fact, looking closely, migrations are part of the startup process which is typically synchronous, at least synchronized to some extent.事实上,仔细观察,迁移是启动过程的一部分,它通常是同步的,至少在某种程度上是同步的。

Requiring JDBC for migration adds to complexity in such an application arrangement.需要 JDBC 进行迁移增加了这种应用程序安排的复杂性。 You are required to include a JDBC driver to an existing R2DBC setup and you need to configure another database connection that points to the same database as with R2DBC.您需要将 JDBC 驱动程序包含到现有的 R2DBC 设置中,并且您需要配置另一个指向与 R2DBC 相同的数据库的数据库连接。 Both requirements are error-prone as they need to be configured to do the exact same thing.这两个要求都容易出错,因为它们需要配置为做完全相同的事情。

Nowadays, application configuration frameworks (Spring Boot, Micronaut, Quarkus) activate functionality when a certain library is available from the classpath.如今,当某个库从类路径可用时,应用程序配置框架(Spring Boot、Micronaut、Quarkus)会激活功能。 Having a JDBC driver configured boots functionality that isn't required for the application but required during bootstrapping and that is sort of a waste of resources.使用 JDBC 驱动程序配置引导功能,这些功能不是应用程序必需的,但在引导过程中是必需的,这有点浪费资源。

Ideally, you configure a single database connection technology that is reused for schema migration and for later data interaction within your application.理想情况下,您可以配置一个单一的数据库连接技术,该技术可重复用于架构迁移和应用程序中以后的数据交互。

Therefore it makes sense to ask Liquibase and Flyway to provide an R2DBC-based integration.因此它是有道理的问Liquibase迁飞提供基于R2DBC整合。

It doesn't seem to me (from an admittedly cursory glance at the front page of the R2DBC web page) that the goals of R2DBC really have anything to do with migrations.在我看来(从 R2DBC 网页的首页粗略一瞥),R2DBC 的目标确实与迁移无关。 That page lists key features as:该页面列出了以下主要功能:

  • Reactive Streams - R2DBC is founded on Reactive Streams providing a fully reactive non-blocking API. Reactive Streams - R2DBC 建立在 Reactive Streams 上,提供了一个完全反应性的非阻塞 API。
  • Relational Databases - R2DBC engages SQL databases with a reactive API, something not possible with the blocking nature of JDBC.关系数据库 - R2DBC 将 SQL 数据库与反应式 API 结合使用,这是 JDBC 的阻塞性质所不可能实现的。
  • Scalable Solutions - Reactive Streams makes it possible to move from the classic one thread per connection approach to a more powerful, more scalable approach.可扩展的解决方案 - Reactive Streams 使从经典的每个连接一个线程的方法转变为更强大、更具可扩展性的方法成为可能。

There is nothing in there that warrants adding R2DBC support to a framework like Liquibase.没有任何内容可以保证向 Liquibase 这样的框架添加 R2DBC 支持。 The JDBC drivers currently in use don't suffer from their use of a non-blocking API, don't really need a "reactive API", and almost certainly don't need to have more than one thread per connection.当前使用的 JDBC 驱动程序不会受到使用非阻塞 API 的影响,不需要“反应式 API”,并且几乎可以肯定每个连接不需要一个以上的线程。

Migration tools are primarily concerned with the shape/structure of the database and not the contents, while R2DBC is aimed at applications that primarily care about the actual data.迁移工具主要关注数据库的形状/结构而不是内容,而 R2DBC 则针对主要关心实际数据的应用程序。

In Summary, I don't see any reason why someone wouldn't use a migration tool like Liquibase that uses JDBC just because their application uses R2DBC, and I don't see any advantage to adding R2DBC support to a tool like Liquibase.总而言之,我看不出有人会因为他们的应用程序使用 R2DBC 而不会使用像 Liquibase 这样使用 JDBC 的迁移工具的任何理由,而且我认为将 R2DBC 支持添加到像 Liquibase 这样的工具没有任何好处。

You can try my package r2dbc-migrate .你可以试试我的包r2dbc-migrate

In minimal configuration (let's suppose that you are using Spring Boot 2.3.0.M3), just add在最小配置中(假设您使用的是 Spring Boot 2.3.0.M3),只需添加

<dependency>
  <groupId>name.nkonev.r2dbc-migrate</groupId>
  <artifactId>r2dbc-migrate-spring-boot-starter</artifactId>
  <version>0.0.24</version>
</dependency>

to pom.xml到 pom.xml

then add .sql files in classpath, for example in /db/migration/然后在类路径中添加 .sql 文件,例如在/db/migration/

then add然后加

r2dbc.migrate.resourcesPath: classpath:/db/migration/*.sql

to your application.yml到您的 application.yml

Both answers above are correct - just wanted to add that if you are looking for fast and easy path and you are using maven then Flyway is probably the most convenient way to operate.以上两个答案都是正确的 - 只是想补充一点,如果您正在寻找快速简便的路径并且您正在使用 maven,那么 Flyway 可能是最方便的操作方式。

All you need to have is Flyway Maven plugin, two pom dependencies and migration sql scripts.您只需要 Flyway Maven 插件、两个 pom 依赖项和迁移 sql 脚本。

Eg.例如。 assuming spring - r2dbc - postgresql you can have migration infrastructure ready in just three simple steps:假设 spring - r2dbc - postgresql 您只需三个简单的步骤就可以准备好迁移基础设施:

(1) Add migration script to resources: (1) 为资源添加迁移脚本:

resources/db/migration/V1_init.sql

(2) add two dependencies to pom (2) 给pom添加两个依赖

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

(3) and one plugin definition in build section: (3) 和构建部分中的一个插件定义:

    <plugin>
        <groupId>org.flywaydb</groupId>
           <artifactId>flyway-maven-plugin</artifactId>
           <version>6.0.0-beta2</version>
    </plugin>

and now you have single maven CLI command to migrate:现在你有一个单独的 maven CLI 命令来迁移:

    mvn flyway:migrate -Dflyway.url=jdbc:postgresql://localhost:5432/test -Dflyway.user=test -Dflyway.password=test

See more Flyway maven plugin docs here在此处查看更多 Flyway maven 插件文档

If anyone face the same problem and doesn't want to use the maven-flyway-plugin , take a look at the FlywayAutoConfiguration class.如果有人面临同样的问题并且不想使用maven-flyway-plugin ,请查看FlywayAutoConfiguration类。 It has @Conditional(FlywayDataSourceCondition.class) , which has @ConditionalOnBean(DataSource.class) inside.它有@Conditional(FlywayDataSourceCondition.class) ,里面有@ConditionalOnBean(DataSource.class) Therefore the bottom line is you should provide a non-reactive database environment to make Flyway work.因此,底线是你应该提供一个非反应性的数据库环境来使 Flyway 工作。 The most straight forward solution is to do something like this:最直接的解决方案是做这样的事情:

@Configuration
public class DataBaseConfig extends AbstractR2dbcConfiguration {

    @Value("${spring.data.postgres.host}")
    private String host;
    @Value("${spring.data.postgres.port}")
    private int port;
    @Value("${spring.data.postgres.database}")
    private String database;
    @Value("${spring.data.postgres.username}")
    private String username;
    @Value("${spring.data.postgres.password}")
    private String password;

    @Bean
    public DatabaseClient databaseClient() {
        return DatabaseClient.create(connectionFactory());
    }

    @Bean
    @Override
    public PostgresqlConnectionFactory connectionFactory() {
        PostgresqlConnectionConfiguration config = PostgresqlConnectionConfiguration.builder()
                .host(host)
                .port(port)
                .database(database)
                .username(username)
                .password(password)
                .build();
        return new PostgresqlConnectionFactory(config);
    }

    @Bean
    public DataSource dataSource() {
        DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
        dataSourceBuilder.driverClassName("org.postgresql.Driver");
        dataSourceBuilder.url("jdbc:postgresql://" + host + ":" + port + "/" + database);
        dataSourceBuilder.username(username);
        dataSourceBuilder.password(password);
        return dataSourceBuilder.build();
    }
}

I went this way as I didn't want to: 1) Run the plugin on each startup;我这样做是因为我不想:1)在每次启动时运行插件; 2) Pass database properties in the comand line 2)在命令行中传递数据库属性

Please, there is a solution for that finally, at least a temporary solution, because there is no Flyway official solution yet (I believe soon we are gonna see a official version).拜托,最终有一个解决方案,至少是一个临时解决方案,因为目前还没有 Flyway 官方解决方案(我相信很快我们就会看到正式版本)。

Please check my post: https://stackoverflow.com/a/62864838/7681696请查看我的帖子: https : //stackoverflow.com/a/62864838/7681696

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM