对于最新的稳定版本,请使用 Spring Data Relational 4.0.4spring-doc.cadn.net.cn

R2DBC 仓库

本章介绍了 R2DBC 的仓库支持的特殊之处。 这部分内容基于使用 Spring Data 仓库一章中所阐述的核心仓库支持。 在阅读本章之前,您应对其中介绍的基本概念有扎实的理解。spring-doc.cadn.net.cn

用法

要访问存储在关系型数据库中的领域实体,您可以使用我们提供的高级仓库(repository)支持,这将显著简化实现过程。 为此,请为您的仓库创建一个接口。 请考虑以下 Person 类:spring-doc.cadn.net.cn

示例 Person 实体
public class Person {

    @Id
    private Long id;
    private String firstname;
    private String lastname;

    // … getters and setters omitted
}

以下示例展示了前述 Person 类的仓库接口:spring-doc.cadn.net.cn

用于持久化 Person 实体的基本仓库接口
public interface PersonRepository extends ReactiveCrudRepository<Person, Long> {

    // additional custom query methods go here
}

要配置 R2DBC 仓库,可以使用 @EnableR2dbcRepositories 注解。 如果没有配置基础包,该基础设施会扫描被注解的配置类所在的包。 以下示例展示了如何为仓库使用 Java 配置:spring-doc.cadn.net.cn

仓库的 Java 配置
@Configuration
@EnableR2dbcRepositories
class ApplicationConfig extends AbstractR2dbcConfiguration {

      @Override
      public ConnectionFactory connectionFactory() {
        return …
      }
}

由于我们的领域仓库扩展了 ReactiveCrudRepository,因此它为您提供了响应式的 CRUD 操作来访问实体。 除了 ReactiveCrudRepository 之外,还有 ReactiveSortingRepository,它添加了类似于 PagingAndSortingRepository 的额外排序功能。 使用仓库实例只需将其通过依赖注入的方式注入到客户端即可。 因此,您可以使用以下代码检索所有的 Person 对象:spring-doc.cadn.net.cn

对 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 的单元测试支持创建了一个应用上下文,该上下文会对测试用例执行基于注解的依赖注入。 在测试方法内部,我们使用 repository 来查询数据库。 我们使用 StepVerifier 作为测试辅助工具,用于验证结果是否符合我们的预期。spring-doc.cadn.net.cn

结果映射

返回接口或 DTO 投影的查询方法,其底层由实际查询生成的结果支持。 接口投影通常首先依赖于将结果映射到领域类型上,以考虑潜在的 @Column 类型映射,而实际的投影代理则使用一个可能部分实例化的实体来暴露投影数据。spring-doc.cadn.net.cn

DTO 投影的结果映射取决于实际的查询类型。 派生查询使用领域类型来映射结果,Spring Data 仅根据领域类型上可用的属性创建 DTO 实例。 在 DTO 中声明领域类型上不存在的属性是不被支持的。spring-doc.cadn.net.cn

基于字符串的查询采用了一种不同的方法,因为实际查询(特别是字段投影)和结果类型声明彼此紧密关联。 与使用 @Query 注解的查询方法一起使用的 DTO 投影会将查询结果直接映射到 DTO 类型。 此时不会考虑域类型上的字段映射。 通过直接使用 DTO 类型,您的查询方法可以受益于更加动态的投影,而不受域模型的限制。spring-doc.cadn.net.cn

使用多个数据库

在使用多个(可能不同的)数据库时,您的应用程序需要采用不同的配置方法。 所提供的 AbstractR2dbcConfiguration 支持类假定使用单一的 ConnectionFactory,并从中推导出 Dialect。 因此,您需要自行定义几个 Bean,以配置 Spring Data R2DBC 与多个数据库协同工作。spring-doc.cadn.net.cn

R2DBC 仓库需要 R2dbcEntityOperations 来实现仓库。 一个简单的配置示例,用于扫描仓库但不使用 AbstractR2dbcConfiguration,如下所示:spring-doc.cadn.net.cn

@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 允许通过 databaseClientRefentityOperationsRef 进行配置。 当连接到多个同类型的数据库时,使用多个 DatabaseClient Bean 非常有用。 当使用方言不同的不同数据库系统时,请改用 @EnableR2dbcRepositories(entityOperationsRef = …)。spring-doc.cadn.net.cn