抢先一步
VMware 提供培训和认证,为您的进步加速。
了解更多我代表团队和所有贡献者高兴地宣布,Spring Data R2DBC 1.0 的第一个候选版本已经发布,可从我们的里程碑仓库获取。此版本包含 60 个问题和拉取请求。它将其基础升级到 R2DBC 0.8 RC1 和 Spring Data Moore GA。
最值得注意的特性包括
AbstractRoutingConnectionFactory
进行 ConnectionFactory
路由。ResourceDatabasePopulator
和 ScriptUtils
进行模式初始化实用工具。TransactionDefinition
进行自动提交和隔离级别控制的传播与重置。ConnectionFactory
路由对于每个操作,DatabaseClient
从用于创建 DatabaseClient
的 ConnectionFactory
获取一个 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.sql
和 data.sql
应用到已配置的 ConnectionFactory
。
此版本附带 Kotlin 扩展,以便在使用 Kotlin 开发应用程序时更符合 Spring Data R2DBC 的习惯用法。
Spring Data R2DBC 提供以下扩展
DatabaseClient
和 Criteria
的具体化泛型支持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 仓库和文档的链接