1. 序章
R2DBC (リアクティブリレーショナルデータベース接続)は、Spring OnePlatform2018中にPivotalによって提示された取り組みです。 SQLデータベースへのリアクティブAPIを作成することを目的としています。
2. 私たちの最初のSpringDataR2DBCプロジェクト
そもそも、R2DBCプロジェクトはごく最近のものです。 現時点では、 PostGres、MSSQL、およびH2のみがR2DBCドライバーを備えています。さらに、すべてのSpring Boot機能を使用することはできません。 したがって、手動で追加する必要のあるいくつかの手順があります。 ただし、SpringDataなどのプロジェクトを活用して支援することができます。
最初にMavenプロジェクトを作成します。 この時点で、R2DBCにはいくつかの依存関係の問題があるため、pom.xmlは通常よりも大きくなります。
この記事の範囲では、データベースとして H2 を使用し、アプリケーション用のリアクティブCRUD関数を作成します。
生成されたプロジェクトのpom.xmlを開き、適切な依存関係といくつかの初期リリースのSpringリポジトリを追加しましょう。
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-r2dbc</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-h2</artifactId>
<version>0.8.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.199</version>
</dependency>
</dependencies>
その他の必要なアーティファクトには、 Lombok、 Spring WebFlux 、およびプロジェクトの依存関係を完了する他のいくつかのアーティファクトが含まれます。
3. コネクションファクトリー
データベースを操作するときは、接続ファクトリが必要です。 したがって、もちろん、R2DBCでも同じことが必要になります。
そこで、インスタンスに接続するための詳細を追加します。
@Configuration
@EnableR2dbcRepositories
class R2DBCConfiguration extends AbstractR2dbcConfiguration {
@Bean
public H2ConnectionFactory connectionFactory() {
return new H2ConnectionFactory(
H2ConnectionConfiguration.builder()
.url("mem:testdb;DB_CLOSE_DELAY=-1;")
.username("sa")
.build()
);
}
}
上記のコードで最初に気付くのは、 @EnableR2dbcRepositoriesです。 Spring Data機能を使用するには、このアノテーションが必要です。 さらに、後で必要になる多くのBeanを提供するため、AbstractR2dbcConfigurationを拡張しています。
4. 私たちの最初のR2DBCアプリケーション
次のステップは、リポジトリを作成することです。
interface PlayerRepository extends ReactiveCrudRepository<Player, Integer> {}
ReactiveCrudRepositoryインターフェースは非常に便利です。 たとえば、基本的なCRUD機能を提供します。
最後に、モデルクラスを定義します。 ボイラープレートコードを回避するためにLombokを使用します。
@Data
@NoArgsConstructor
@AllArgsConstructor
class Player {
@Id
Integer id;
String name;
Integer age;
}
5. テスト
コードをテストする時が来ました。 それでは、いくつかのテストケースを作成することから始めましょう。
@Test
public void whenDeleteAll_then0IsExpected() {
playerRepository.deleteAll()
.as(StepVerifier::create)
.expectNextCount(0)
.verifyComplete();
}
@Test
public void whenInsert6_then6AreExpected() {
insertPlayers();
playerRepository.findAll()
.as(StepVerifier::create)
.expectNextCount(6)
.verifyComplete();
}
6. カスタムクエリ
カスタムクエリを生成することもできます。 追加するには、PlayerRepositoryを変更する必要があります。
@Query("select id, name, age from player where name = $1")
Flux<Player> findAllByName(String name);
@Query("select * from player where age = $1")
Flux<Player> findByAge(int age);
既存のテストに加えて、最近更新されたリポジトリにテストを追加します。
@Test
public void whenSearchForCR7_then1IsExpected() {
insertPlayers();
playerRepository.findAllByName("CR7")
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
}
@Test
public void whenSearchFor32YearsOld_then2AreExpected() {
insertPlayers();
playerRepository.findByAge(32)
.as(StepVerifier::create)
.expectNextCount(2)
.verifyComplete();
}
private void insertPlayers() {
List<Player> players = Arrays.asList(
new Player(1, "Kaka", 37),
new Player(2, "Messi", 32),
new Player(3, "Mbappé", 20),
new Player(4, "CR7", 34),
new Player(5, "Lewandowski", 30),
new Player(6, "Cavani", 32)
);
playerRepository.saveAll(players).subscribe();
}
7. バッチ
R2DBCのもう1つの機能は、バッチを作成することです。 バッチは、個々の操作よりもパフォーマンスが高いため、複数のSQLステートメントを実行する場合に役立ちます。
バッチを作成するには、接続オブジェクトが必要です。
Batch batch = connection.createBatch();
アプリケーションがBatchインスタンスを作成した後、必要な数のSQLステートメントを追加できます。 これを実行するには、 execute()メソッドを呼び出します。 バッチの結果はPublisherであり、各ステートメントの結果オブジェクトを返します。
それでは、コードに飛び込んで、バッチを作成する方法を見てみましょう。
@Test
public void whenBatchHas2Operations_then2AreExpected() {
Mono.from(factory.create())
.flatMapMany(connection -> Flux.from(connection
.createBatch()
.add("select * from player")
.add("select * from player")
.execute()))
.as(StepVerifier::create)
.expectNextCount(2)
.verifyComplete();
}
8. 結論
要約すると、R2DBCはまだ初期段階にあります。 これは、SQLデータベースへのリアクティブAPIを定義するSPIを作成する試みです。 Spring WebFlux と併用すると、R2DBCを使用して、データを上からデータベースに至るまで非同期で処理するアプリケーションを作成できます。
いつものように、コードはGitHubで入手できます。
つまり、この作業により、完全に非ブロッキングのドライバーを使用してデータベース接続が作成されます。
このチュートリアルでは、Spring DataR2BDCを使用したアプリケーションの例を見ていきます。 より低レベルのR2DBCAPIのガイドについては、以前の記事をご覧ください。