Spring Data R2DBC 1.0 RC1 发布

发布 | Mark Paluch | 2019 年 10 月 01 日 | ...

我代表团队和所有贡献者高兴地宣布,Spring Data R2DBC 1.0 的第一个候选版本已经发布,可从我们的里程碑仓库获取。此版本包含 60 个问题和拉取请求。它将其基础升级到 R2DBC 0.8 RC1 和 Spring Data Moore GA。

最值得注意的特性包括

  • 通过 AbstractRoutingConnectionFactory 进行 ConnectionFactory 路由。
  • 通过 ResourceDatabasePopulatorScriptUtils 进行模式初始化实用工具。
  • 通过 TransactionDefinition 进行自动提交和隔离级别控制的传播与重置。
  • 支持实体级转换器。
  • 用于具体化泛型和协程的 Kotlin 扩展。
  • 添加可插拔机制以注册方言。
  • API 改进。

ConnectionFactory 路由

对于每个操作,DatabaseClient 从用于创建 DatabaseClientConnectionFactory 获取一个 Connection

一般想法是,一个路由 ConnectionFactory 充当中介——而“真实”的 ConnectionFactory 是在运行时根据查找键动态确定的。一个潜在的用例是通过使用指向不同数据库的多个 ConnectionFactory 实例来满足多租户需求。为了让路由 ConnectionFactory 确定使用哪个 ConnectionFactory,它需要上下文信息。Spring Data R2DBC 提供了一个 AbstractRoutingConnectionFactory,它可以返回一个用于查找正确 ConnectionFactory 的查找键。

响应式流可以使用 Project Reactor 的 Context 将上下文信息附加到订阅中。

路由 ConnectionFactory 的示例实现可能如下所示

class RoutingConnectionFactory extends AbstractRoutingConnectionFactory {

    public static final String ROUTING_KEY = "routing-key";

    @Override
    protected Mono<Object> determineCurrentLookupKey() {
        return Mono.subscriberContext().filter(it -> it.hasKey(ROUTING_KEY)).map(it -> it.get(ROUTING_KEY));
    }
}

以下清单展示了如何初始化连接工厂,其中包含查找键与目标 ConnectionFactory 之间的映射

RoutingConnectionFactory connectionFactory = new RoutingConnectionFactory();
Map<String, ConnectionFactory> factories = new HashMap<>();
factories.put("customer1", …);
factories.put("customer2", …);
connectionFactory.setTargetConnectionFactories(factories);
connectionFactory.afterPropertiesSet();

您可以通过使用路由 ConnectionFactory 来创建 DatabaseClient,以便为每个订阅确定适当的 ConnectionFactory。如以下清单所示,路由键本身附加到 Context 并由 RoutingConnectionFactory 进行评估。

DatabaseClient client = DatabaseClient.create(connectionFactory);

Context routingContext = Context.of(ROUTING_KEY, "customer1");

Flux<User> users = client.execute("SELECT first_name, last_name FROM user")
                .as(User.class)
                .fetch()
                .all()
                .subscriberContext(routingContext);

模式初始化

org.springframework.data.r2dbc.connectionfactory.init 包提供了初始化现有 ConnectionFactory 的支持。有时您可能需要初始化运行在某个服务器上的实例或嵌入式数据库。以下清单展示了如何注册和配置一个 ConnectionFactoryInitializer bean,通过 ConnectionFactory 初始化数据库。

@Configuration
public class InitializerConfiguration {

  @Bean
  public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {

    ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
    initializer.setConnectionFactory(connectionFactory);

    CompositeDatabasePopulator populator = new CompositeDatabasePopulator();
    populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("com/foo/sql/db-schema.sql")));
    populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("com/foo/sql/test-data1.sql")));
    initializer.setDatabasePopulator(populator);

    return initializer;
  }
}

Spring Boot R2DBC 自动配置使用了此初始化支持,将 schema.sqldata.sql 应用到已配置的 ConnectionFactory

Kotlin 扩展

此版本附带 Kotlin 扩展,以便在使用 Kotlin 开发应用程序时更符合 Spring Data R2DBC 的习惯用法。

Spring Data R2DBC 提供以下扩展

  • DatabaseClientCriteria 的具体化泛型支持
  • DatabaseClient 的 Kotlin Coroutines 支持

在 Java 中检索 User 对象列表,通常会写如下代码

Flux<User> characters = client.select().from(User.class).fetch().all();

使用 Kotlin 和 Spring Data 扩展,您可以改写如下代码

val users =  client.select().from<User>().fetch().all()

Kotlin Coroutines 是 Kotlin 的轻量级线程,允许以命令式风格编写非阻塞代码。Spring Data R2DBC 的协程扩展利用响应式基础设施暴露可 suspend 的函数,并将 Flux 结果桥接到 Kotlin 的 Flow 类型。

以下示例展示了协程与 Spring Framework 的 TransactionalOperator 一起使用,以原子方式插入两行数据

operator.executeAndAwait {
  client.execute("INSERT INTO person VALUES(:first_name, :last_name)")
        .bind("first_name", "John")
        .bind("last_name", "Doe")
        .await()
  client.execute("INSERT INTO person_events VALUES(:first_name, :last_name, :event_type)")
        .bind("first_name", "John")
        .bind("last_name", "Doe")
        .bind("event_type", "CREATED")
        .await()
}

请注意,大多数 suspend 方法以 await 结尾,作为协程方法的指示。

可插拔方言

截至目前,R2DBC 驱动生态系统仅包含少数已知驱动,但驱动数量正在增长。为了实现与额外驱动的无缝集成,Spring Data R2DBC 暴露了一个用于 R2dbcDialect 注册的扩展点。Spring Data R2DBC 可以通过 Spring 的 META-INF/spring.factories 机制注册实现 org.springframework.data.r2dbc.dialect.DialectResolver$R2dbcDialectProvider 接口的类来自动发现 R2dbcDialect。以下清单展示了如何做到这一点

public class MyDialectProvider implements DialectResolver.R2dbcDialectProvider {

    @Override
    public Optional<R2dbcDialect> getDialect(ConnectionFactory connectionFactory) {

        if (connectionFactory.getMetadata().getName().equals("my-dastabase")) {
            return Optional.of(…);
        }
        return Optional.empty();
    }
}

spring.factories

org.springframework.data.r2dbc.dialect.DialectResolver$R2dbcDialectProvider=com.example.MyDialectProvider

构件坐标

如果您使用 Maven,请将以下行添加到您的 pom.xml 文件中以升级到 Spring Data R2DBC 1.0 RC1

<dependencies>
  <dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-r2dbc</artifactId>
    <version>1.0.0.RC1</version>
  </dependency>
</dependencies>

<!-- R2DBC 0.8.0.RC1 required -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>io.r2dbc</groupId>
      <artifactId>r2dbc-bom</artifactId>
      <version>Arabba-RC1</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<repositories>
  <repository>
    <id>spring-milestone</id>
    <url>https://repo.spring.io/milestone</url>
  </repository>
</repositories>

后续步骤

R2DBC 0.8.0 RC1 最近发布,我们预计今年晚些时候会有 GA 版本发布。我们正在努力推出 Spring Data R2DBC 1.0 GA 版本,一旦 R2DBC 本身发布 GA,我们将发布下一个版本。我们的待办事项列表包含一系列增强功能,例如查询派生、乐观锁以及允许查询拦截以在执行绑定和 SQL 语句之前对其进行修改。

最后,这里是变更日志、GitHub 仓库和文档的链接

订阅 Spring 资讯

通过 Spring 资讯保持连接

订阅

抢先一步

VMware 提供培训和认证,为您的进步加速。

了解更多

获取支持

Tanzu Spring 通过一个简单的订阅提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看全部