Couchbaseを使用したSpring Data Reactive Repositories

1. 概要

このチュートリアルでは、https://www.baeldung.com/spring-data-couchbase [Spring Dataを使用したCouchbase]リポジトリで、リアクティブな方法でデータベース操作を設定および実装する方法を学びます。
__ReactiveCrudRepository __and _ReactiveSortingRepository_の基本的な使用法について説明します。 さらに、_AbstractReactiveCouchbaseConfiguration_を使用してテストアプリケーションを構成します。

2. Mavenの依存関係

まず、必要な依存関係を追加しましょう。
<dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-core</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-couchbase-reactive</artifactId>
</dependency>
https://search.maven.org/search?q=g:org.springframework.boot%20AND%20a:spring-boot-starter-data-couchbase-reactive[spring-boot-starter-data-couchbase-reactive ]依存関係には、リアクティブAPIを使用してCouchbaseで操作するために必要なすべてが含まれています。
また、https://search.maven.org/search?q = g:io.projectreactor%20AND%20a:reactor-core [reactor-core]依存関係を含めてProject Reactor APIを使用します。

3. 設定

次に、Couchbaseとアプリケーション間の接続設定を定義しましょう。
まず、プロパティを保持するクラスを作成します。
@Configuration
public class CouchbaseProperties {

    private List<String> bootstrapHosts;
    private String bucketName;
    private String bucketPassword;
    private int port;

    public CouchbaseProperties(
      @Value("${spring.couchbase.bootstrap-hosts}") List<String> bootstrapHosts,
      @Value("${spring.couchbase.bucket.name}") String bucketName,
      @Value("${spring.couchbase.bucket.password}") String bucketPassword,
      @Value("${spring.couchbase.port}") int port) {
        this.bootstrapHosts = Collections.unmodifiableList(bootstrapHosts);
        this.bucketName = bucketName;
        this.bucketPassword = bucketPassword;
        this.port = port;
    }

    // getters
}
リアクティブサポートを使用するには、_AbstractReactiveCouchbaseConfiguration_を拡張する構成クラスを作成する必要があります。
@Configuration
@EnableReactiveCouchbaseRepositories("com.baeldung.couchbase.domain.repository")
public class ReactiveCouchbaseConfiguration extends AbstractReactiveCouchbaseConfiguration {

    private CouchbaseProperties couchbaseProperties;

    public ReactiveCouchbaseConfiguration(CouchbaseProperties couchbaseProperties) {
        this.couchbaseProperties = couchbaseProperties;
    }

    @Override
    protected List<String> getBootstrapHosts() {
        return couchbaseProperties.getBootstrapHosts();
    }

    @Override
    protected String getBucketName() {
        return couchbaseProperties.getBucketName();
    }

    @Override
    protected String getBucketPassword() {
        return couchbaseProperties.getBucketPassword();
    }

    @Override
    public CouchbaseEnvironment couchbaseEnvironment() {
        return DefaultCouchbaseEnvironment
          .builder()
          .bootstrapHttpDirectPort(couchbaseProperties.getPort())
          .build();
    }
}
さらに、_ @ EnableReactiveCouchbaseRepositories_を使用して、指定したパッケージの下にあるリアクティブリポジトリを有効にしました。
さらに、Couchbase接続ポートを渡すために_couchbaseEnvironment()_をオーバーライドしました。

4. リポジトリ

このセクションでは、リアクティブリポジトリを作成して使用する方法を学習します。 *デフォルトでは、「すべて」https://docs.couchbase.com/server/6.0/learn/views/views-intro.html[view]がほとんどのCRUD操作をサポートしています。 カスタムリポジトリメソッドはlink:/n1ql-couchbase[N1QL]によってサポートされています。*クラスターがN1QLをサポートしていない場合、_UnsupportedCouchbaseFeatureException_が初期化中にスローされます。
最初に、リポジトリが動作するPOJOクラスを作成しましょう。
@Document
public class Person {
    @Id private UUID id;
    private String firstName;

   //getters and setters
}

4.1. ビューベースのリポジトリ

次に、_Person_のリポジトリを作成します。
@Repository
@ViewIndexed(designDoc = ViewPersonRepository.DESIGN_DOCUMENT)
public interface ViewPersonRepository extends ReactiveCrudRepository<Person, UUID> {

    String DESIGN_DOCUMENT = "person";
}
リポジトリは、Reactor APIを使用してCouchbaseと対話するために、_ReactiveCrudRepository_インターフェースを拡張します。
さらに、カスタムメソッドを追加し、_ @ View_アノテーションを使用してビューベースにすることができます。
@View(designDocument = ViewPersonRepository.DESIGN_DOCUMENT)
Flux<Person> findByFirstName(String firstName);
デフォルトでは、クエリは_byFirstName_という名前のビューを探します。 カスタムビュー名を指定する場合は、_viewName_引数を使用する必要があります。
最後に、テスト購読者の助けを借りて簡単なCRUDテストを作成しましょう。
@Test
public void shouldSavePerson_findById_thenDeleteIt() {
    final UUID id = UUID.randomUUID();
    final Person person = new Person(id, "John");
    personRepository
      .save(person)
      .subscribe();

    final Mono<Person> byId = personRepository.findById(id);

    StepVerifier
      .create(byId)
      .expectNextMatches(result -> result
        .getId()
        .equals(id))
      .expectComplete()
      .verify();

    personRepository
      .delete(person)
      .subscribe();
}

[[n1ql based]]
==== 4.2. N1QL /ビューベースのリポジトリ

次に、N1QLクエリを使用する_Person_のリアクティブリポジトリを作成します。
@Repository
@N1qlPrimaryIndexed
public interface N1QLPersonRepository extends ReactiveCrudRepository<Person, UUID> {
    Flux<Person> findAllByFirstName(String firstName);
}
リポジトリーは、Reactor APIも使用するために_ReactiveCrudRepository_を拡張します。 さらに、カスタムの_findAllByFirstName_メソッドを追加しました。これにより、N1QLのクエリが作成されます。
その後、_findAllByFirstName_メソッドのテストを追加しましょう。
@Test
public void shouldFindAll_byLastName() {
    final String firstName = "John";
    final Person matchingPerson = new Person(UUID.randomUUID(), firstName);
    final Person nonMatchingPerson = new Person(UUID.randomUUID(), "NotJohn");
    personRepository
      .save(matchingPerson)
      .subscribe();
    personRepository
      .save(nonMatchingPerson)
      .subscribe();

    final Flux<Person> allByFirstName = personRepository.findAllByFirstName(firstName);

    StepVerifier
      .create(allByFirstName)
      .expectNext(matchingPerson)
      .verifyComplete();
}
さらに、ソート抽象化を使用して人を取得できるリポジトリを作成します。
@Repository
public interface N1QLSortingPersonRepository extends ReactiveSortingRepository<Person, UUID> {
    Flux<Person> findAllByFirstName(String firstName, Sort sort);
}
最後に、データが実際にソートされているかどうかを確認するテストを作成しましょう。
@Test
public void shouldFindAll_sortedByFirstName() {
    final Person firstPerson = new Person(UUID.randomUUID(), "John");
    final Person secondPerson = new Person(UUID.randomUUID(), "Mikki");
    personRepository
      .save(firstPerson)
      .subscribe();
    personRepository
      .save(secondPerson)
      .subscribe();

    final Flux<Person> allByFirstName = personRepository
      .findAll(Sort.by(Sort.Direction.DESC, "firstName"));

    StepVerifier
      .create(allByFirstName)
      .expectNextMatches(person -> person
        .getFirstName()
        .equals(secondPerson.getFirstName()))
      .expectNextMatches(person -> person
        .getFirstName()
        .equals(firstPerson.getFirstName()))
      .verifyComplete();
}

5. 結論

この記事では、CouchbaseとSpring Data Reactiveフレームワークを使用したリアクティブプログラミングを使用してリポジトリを使用する方法を学びました。
いつものように、これらの例のコードはhttps://github.com/eugenp/tutorials/tree/master/spring-5-data-reactive[Github上]で入手できます。