R2DBC Repositories
-
使用 ReactiveCrudRepository 轻松访问关系型数据库中的实体
-
复杂存储库支持,允许创建查询方法和自定义投影
-
支持反应式 CRUD 操作,包括分页和排序
-
使用 DTO 投影将查询结果映射到接口或 DTO
-
为处理多个数据库提供配置选项
本章指出了 R2DBC 存储库支持的特殊性。这是在 Working with Spring Data Repositories中解释的核心存储库支持的基础上构建的。在阅读本章之前,你应该对那里解释的基本概念有深入的了解。
This chapter points out the specialties for repository support for R2DBC. This builds on the core repository support explained in Working with Spring Data Repositories. Before reading this chapter, you should have a sound understanding of the basic concepts explained there.
Usage
若要访问存储在关系型数据库中的域实体,您可以使用我们复杂的存储库支持,这极大地简化了实现。为此,请为您的存储库创建一个界面。考虑以下 Person
类:
To access domain entities stored in a relational database, you can use our sophisticated repository support that eases implementation quite significantly.
To do so, create an interface for your repository.
Consider the following Person
class:
public class Person {
@Id
private Long id;
private String firstname;
private String lastname;
// … getters and setters omitted
}
以下示例显示了前面 Person
类的存储库界面:
The following example shows a repository interface for the preceding Person
class:
public interface PersonRepository extends ReactiveCrudRepository<Person, Long> {
// additional custom query methods go here
}
若要配置 R2DBC 存储库,您可以使用 @EnableR2dbcRepositories
注释。如果未配置基本包,基础结构将扫描带注释的配置类的包。以下示例演示如何将 Java 配置用于存储库:
To configure R2DBC repositories, you can use the @EnableR2dbcRepositories
annotation.
If no base package is configured, the infrastructure scans the package of the annotated configuration class.
The following example shows how to use Java configuration for a repository:
@Configuration
@EnableR2dbcRepositories
class ApplicationConfig extends AbstractR2dbcConfiguration {
@Override
public ConnectionFactory connectionFactory() {
return …
}
}
由于我们的域存储库扩展了 ReactiveCrudRepository
,因此它为您提供了反应式 CRUD 操作来访问实体。在 ReactiveCrudRepository
之上,还有 ReactiveSortingRepository
,它添加了类似于 PagingAndSortingRepository
的其他排序功能。只需依赖注入它到客户端,即可使用存储库实例。因此,您可以使用以下代码检索所有 Person
对象:
Because our domain repository extends ReactiveCrudRepository
, it provides you with reactive CRUD operations to access the entities.
On top of ReactiveCrudRepository
, there is also ReactiveSortingRepository
, which adds additional sorting functionality similar to that of PagingAndSortingRepository
.
Working with the repository instance is merely a matter of dependency injecting it into a client.
Consequently, you can retrieve all Person
objects with the following code:
Unresolved include directive in modules/ROOT/pages/r2dbc/repositories.adoc - include::example$r2dbc/PersonRepositoryTests.java[]
前面的示例使用 Spring 的单元测试支持创建应用程序上下文,该支持对测试用例执行基于注释的依赖注入。在测试方法中,我们使用存储库查询数据库。我们使用 StepVerifier
作为测试辅助工具,以根据结果验证我们的预期。
The preceding example creates an application context with Spring’s unit test support, which performs annotation-based dependency injection into test cases.
Inside the test method, we use the repository to query the database.
We use StepVerifier
as a test aid to verify our expectations against the results.
Result Mapping
返回接口或 DTO 投影的查询方法由实际查询生成的结果支持。接口投影通常首先依赖于将结果映射到域类型以考虑潜在的 @Column
类型映射,而实际投影代理使用潜在的部分物化实体来公开投影数据。
A query method returning an Interface- or DTO projection is backed by results produced by the actual query.
Interface projections generally rely on mapping results onto the domain type first to consider potential @Column
type mappings and the actual projection proxy uses a potentially partially materialized entity to expose projection data.
DTO 投影的结果映射取决于实际的查询类型。派生查询使用域类型映射结果,而 Spring Data 仅从域类型上可用的属性创建 DTO 实例。不支持在 DTO 中声明域类型上不可用的属性。
Result mapping for DTO projections depends on the actual query type. Derived queries use the domain type to map results, and Spring Data creates DTO instances solely from properties available on the domain type. Declaring properties in your DTO that are not available on the domain type is not supported.
基于字符串的查询使用不同的方法,因为实际查询(特别是字段投影)和结果类型声明紧密相连。用于 @Query
注释的查询方法的 DTO 投影直接将查询结果映射到 DTO 类型。不考虑域类型上的字段映射。通过直接使用 DTO 类型,您的查询方法可以受益于不受域模型限制的更动态投影。
String-based queries use a different approach since the actual query, specifically the field projection, and result type declaration are close together.
DTO projections used with query methods annotated with @Query
map query results directly into the DTO type.
Field mappings on the domain type are not considered.
Using the DTO type directly, your query method can benefit from a more dynamic projection that isn’t restricted to the domain model.
Working with multiple Databases
在处理多个可能不同的数据库时,您的应用程序将需要不同的配置方法。提供的 AbstractR2dbcConfiguration
支持类假定有一个 ConnectionFactory
,从中可以导出 Dialect
。也就是说,您需要自己定义一些 Bean,以配置 Spring Data R2DBC 以便与多个数据库一起使用。
When working with multiple, potentially different databases, your application will require a different approach to configuration.
The provided AbstractR2dbcConfiguration
support class assumes a single ConnectionFactory
from which the Dialect
gets derived.
That being said, you need to define a few beans yourself to configure Spring Data R2DBC to work with multiple databases.
R2DBC 存储库需要 R2dbcEntityOperations
来实现存储库。用于扫描存储库而无需使用 AbstractR2dbcConfiguration
的简单配置如下所示:
R2DBC repositories require R2dbcEntityOperations
to implement repositories.
A simple configuration to scan for repositories without using AbstractR2dbcConfiguration
looks like:
@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
允许通过 databaseClientRef
或 entityOperationsRef
进行配置。当连接到同一类型的多个数据库时,使用各种 DatabaseClient
Bean 很有用。当使用方言不同的不同数据库系统时,请使用 @EnableR2dbcRepositories
(entityOperationsRef = …)` 。
Note that @EnableR2dbcRepositories
allows configuration either through databaseClientRef
or entityOperationsRef
.
Using various DatabaseClient
beans is useful when connecting to multiple databases of the same type.
When using different database systems that differ in their dialect, use @EnableR2dbcRepositories
(entityOperationsRef = …)` instead.