R2DBC 仓库
本章指出 R2DBC 在仓库支持方面的特别之处。它建立在使用 Spring Data 仓库中讲解的核心仓库支持之上。在阅读本章之前,您应充分理解其中讲解的基本概念。
用法
要访问存储在关系型数据库中的领域实体,您可以使用我们完善的仓库支持,它能显著简化实现。为此,请为您的仓库创建一个接口。请看以下 Person 类:
public class Person {
@Id
private Long id;
private String firstname;
private String lastname;
// … getters and setters omitted
}
以下示例展示了针对前述 Person 类的仓库接口:
public interface PersonRepository extends ReactiveCrudRepository<Person, Long> {
// additional custom query methods go here
}
要配置 R2DBC 仓库,您可以使用 @EnableR2dbcRepositories 注解。如果未配置基础包,基础设施会扫描被注解配置类所在的包。以下示例展示如何为仓库使用 Java 配置:
@Configuration
@EnableR2dbcRepositories
class ApplicationConfig extends AbstractR2dbcConfiguration {
@Override
public ConnectionFactory connectionFactory() {
return …
}
}
由于我们的领域仓库继承了 ReactiveCrudRepository,它为您提供了响应式 CRUD 操作来访问实体。在 ReactiveCrudRepository 之上,还有 ReactiveSortingRepository,它添加了类似于 PagingAndSortingRepository 的额外排序功能。使用仓库实例只需将其依赖注入到客户端即可。因此,您可以用以下代码检索所有 Person 对象:
@ExtendWith(SpringExtension.class)
@ContextConfiguration
class PersonRepositoryTests {
@Autowired
PersonRepository repository;
@Test
void readsAllEntitiesCorrectly() {
repository.findAll()
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
}
@Test
void readsEntitiesByNameCorrectly() {
repository.findByFirstname("Hello World")
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
}
}
前述示例使用 Spring 的单元测试支持创建了一个应用上下文,该支持会对测试用例执行基于注解的依赖注入。在测试方法内部,我们使用仓库来查询数据库。我们使用 StepVerifier 作为测试辅助手段,将我们的预期与结果进行核对。
结果映射
返回接口投影或 DTO 投影的查询方法,其背后是实际查询产生的结果。接口投影通常依赖于先将结果映射到领域类型,以考虑可能的 @Column 类型映射,而实际的投影代理则使用一个可能部分物化的实体来暴露投影数据。
DTO 投影的结果映射取决于实际的查询类型。派生查询使用领域类型来映射结果,Spring Data 仅从领域类型上可用的属性创建 DTO 实例。在 DTO 中声明领域类型上不可用的属性是不受支持的。
基于字符串的查询采用不同的方式,因为实际查询(特别是字段投影)与结果类型声明彼此靠近。与 @Query 注解的查询方法配合使用的 DTO 投影,会将查询结果直接映射到 DTO 类型。不考虑领域类型上的字段映射。通过直接使用 DTO 类型,您的查询方法可以受益于一种更动态的、不受领域模型限制的投影。
使用多个数据库
当使用多个、可能各不相同的数据库时,您的应用需要采用不同的配置方式。所提供的 AbstractR2dbcConfiguration 支持类假定只有一个 ConnectionFactory,并从中派生 Dialect。也就是说,您需要自己定义若干 bean,以配置 Spring Data R2DBC 使其能与多个数据库协同工作。
R2DBC 仓库需要 R2dbcEntityOperations 来实现仓库。不使用 AbstractR2dbcConfiguration 而扫描仓库的简单配置如下所示:
@Configuration
@EnableR2dbcRepositories(basePackages = "com.acme.mysql", entityOperationsRef = "mysqlR2dbcEntityOperations")
static class MySQLConfiguration {
@Bean
@Qualifier("mysql")
public ConnectionFactory mysqlConnectionFactory() {
return …
}
@Bean
public R2dbcEntityOperations mysqlR2dbcEntityOperations(@Qualifier("mysql") ConnectionFactory connectionFactory) {
DatabaseClient databaseClient = DatabaseClient.create(connectionFactory);
return new R2dbcEntityTemplate(databaseClient, MySqlDialect.INSTANCE);
}
}
请注意,@EnableR2dbcRepositories 允许通过 entityOperationsRef 进行配置。在连接多个同类型数据库时,使用各种 DatabaseClient bean 会很有用。当使用方言各不相同的不同数据库系统时,请改用 @EnableR2dbcRepositories(entityOperationsRef = …)。