R2DBC 儲存庫

本章重點介紹 R2DBC 儲存庫支援的特殊性。這建立在 使用 Spring Data 儲存庫 中說明的核心儲存庫支援之上。在閱讀本章之前,您應該對其中說明的基本概念有充分的理解。

用法

若要存取儲存在關聯式資料庫中的網域實體,您可以使用我們精密的儲存庫支援,大幅簡化實作。若要執行此操作,請為您的儲存庫建立介面。請考慮以下 Person 類別

範例 Person 實體
public class Person {

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

  // … getters and setters omitted
}

以下範例顯示了先前 Person 類別的儲存庫介面

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

  // additional custom query methods go here
}

若要配置 R2DBC 儲存庫,您可以使用 @EnableR2dbcRepositories 註解。如果未配置基礎套件,基礎架構會掃描帶註解的配置類別的套件。以下範例顯示如何使用 Java 配置儲存庫

儲存庫的 Java 配置
@Configuration
@EnableR2dbcRepositories
class ApplicationConfig extends AbstractR2dbcConfiguration {

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

由於我們的網域儲存庫擴展了 ReactiveCrudRepository,因此它為您提供了反應式 CRUD 操作來存取實體。在 ReactiveCrudRepository 之上,還有 ReactiveSortingRepository,它增加了額外的排序功能,類似於 PagingAndSortingRepository 的功能。使用儲存庫實例僅僅是將其依賴注入到用戶端的問題。因此,您可以使用以下程式碼檢索所有 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 的單元測試支援建立應用程式上下文,該支援對測試案例執行基於註解的依賴注入。在測試方法內部,我們使用儲存庫來查詢資料庫。我們使用 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 允許透過 databaseClientRefentityOperationsRef 進行配置。當連接到相同類型的多個資料庫時,使用各種 DatabaseClient bean 非常有用。當使用方言不同的不同資料庫系統時,請改用 @EnableR2dbcRepositories(entityOperationsRef = …)