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
に加えて、PagingAndSortingRepository
と同様のソート機能を追加する ReactiveSortingRepository
もあります。リポジトリインスタンスの操作は、それをクライアントに挿入する依存関係の問題にすぎません。次のコードですべての 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
サポートクラスは、Dialect
が派生する単一の ConnectionFactory
を想定しています。そうは言っても、複数のデータベースで動作するように Spring Data R2DBC を構成するには、いくつかの Bean を自分で定義する必要があります。
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
は、databaseClientRef
または entityOperationsRef
のいずれかを介して構成できることに注意してください。さまざまな DatabaseClient
Bean を使用すると、同じ型の複数のデータベースに接続するときに便利です。ダイアレクトが異なる異なるデータベースシステムを使用する場合は、代わりに @EnableR2dbcRepositories
(entityOperationsRef = …) を使用します。