R2DBC Repository

本章重點介紹了 R2DBC 的 Repository 支援的特性。這基於 使用 Spring Data Repository 中解釋的核心 Repository 支援。在閱讀本章之前,您應該對其中解釋的基本概念有深入的理解。

使用

為了訪問儲存在關係型資料庫中的領域實體,您可以使用我們強大的 Repository 支援,它極大地簡化了實現。為此,請為您的 Repository 建立一個介面。考慮以下 Person

示例 Person 實體
public class Person {

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

  // … getters and setters omitted
}

以下示例顯示了前述 Person 類的 Repository 介面

用於持久化 Person 實體的基本 Repository 介面
public interface PersonRepository extends ReactiveCrudRepository<Person, Long> {

  // additional custom query methods go here
}

要配置 R2DBC Repository,您可以使用 @EnableR2dbcRepositories 註解。如果未配置基礎包,基礎設施將掃描帶註解的配置類所在的包。以下示例展示瞭如何使用 Java 配置來配置 Repository

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

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

由於我們的領域 Repository 擴充套件了 ReactiveCrudRepository,它提供了響應式 CRUD 操作來訪問實體。在 ReactiveCrudRepository 的基礎上,還有 ReactiveSortingRepository,它增加了類似於 PagingAndSortingRepository 的附加排序功能。使用 Repository 例項僅僅是將其依賴注入到客戶端即可。因此,您可以使用以下程式碼檢索所有 Person 物件

對 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 作為測試輔助工具來驗證我們對結果的預期。

結果對映

返回 Interface 或 DTO 投影的查詢方法由實際查詢產生的結果支援。介面投影通常首先依賴於將結果對映到領域型別,以考慮潛在的 @Column 型別對映,並且實際的投影代理使用可能部分物化的實體來暴露投影資料。

DTO 投影的結果對映取決於實際的查詢型別。派生查詢使用領域型別來對映結果,Spring Data 僅從領域型別上可用的屬性建立 DTO 例項。在您的 DTO 中宣告領域型別上不可用的屬性是不受支援的。

基於字串的查詢使用不同的方法,因為實際的查詢(特別是欄位投影)和結果型別宣告緊密相關。使用 @Query 註解的查詢方法所使用的 DTO 投影將查詢結果直接對映到 DTO 型別。領域型別上的欄位對映不會被考慮。直接使用 DTO 型別,您的查詢方法可以從更動態的投影中受益,這種投影不受領域模型的限制。

使用多個數據庫

當使用多個可能不同的資料庫時,您的應用程式需要一種不同的配置方法。提供的 AbstractR2dbcConfiguration 支援類假定存在單個 ConnectionFactoryDialect 從中派生。也就是說,您需要自己定義一些 bean 來配置 Spring Data R2DBC 以使用多個數據庫。

R2DBC Repository 需要 R2dbcEntityOperations 來實現 Repository。一個不使用 AbstractR2dbcConfiguration 的簡單 Repository 掃描配置如下所示

@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 = …) 。