MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Spring Data Reactive Repositories mit MongoDB

1. Einführung

In diesem Lernprogramm erfahren Sie, wie Sie Datenbankoperationen mithilfe von reaktiver Programmierung über Spring Data Reactive Repositories mit MongoDB konfigurieren und implementieren.

Wir gehen die grundlegende Verwendung von ReactiveCrud durch Repository, ReactiveMongoRepository , sowie ReactiveMongoTemplate.

Obwohl diese Implementierungen reaktive Programmierung verwenden, ist dies nicht der Hauptfokus dieses Tutorials.

2. Umwelt

Um Reactive MongoDB zu verwenden, müssen wir die Abhängigkeit zu unserer pom.xml. hinzufügen

Wir werden auch eine eingebettete MongoDB zum Testen hinzufügen:

<dependencies>
    // ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
    </dependency>
    <dependency>
        <groupId>de.flapdoodle.embed</groupId>
        <artifactId>de.flapdoodle.embed.mongo</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

3. Konfiguration

Um die reaktive Unterstützung zu aktivieren, müssen wir die @EnableReactiveMongoRepositories verwenden zusammen mit einigen Infrastruktureinstellungen:

@EnableReactiveMongoRepositories
public class MongoReactiveApplication
  extends AbstractReactiveMongoConfiguration {

    @Bean
    public MongoClient mongoClient() {
        return MongoClients.create();
    }

    @Override
    protected String getDatabaseName() {
        return "reactive";
    }
}

Beachten Sie, dass das Obige erforderlich wäre, wenn wir die eigenständige MongoDB-Installation verwenden würden. Da wir in unserem Beispiel jedoch Spring Boot mit eingebettetem MongoDB verwenden, ist die obige Konfiguration nicht erforderlich.

4. Erstellen eines Dokuments

Lassen Sie uns für die folgenden Beispiele ein Konto erstellen class und kommentieren Sie es mit @Document um es in den Datenbankoperationen zu verwenden:

@Document
public class Account {
 
    @Id
    private String id;
    private String owner;
    private Double value;
 
    // getters and setters
}

5. Reaktive Repositories verwenden

Wir sind bereits mit dem Repository-Programmiermodell vertraut, mit den bereits definierten CRUD-Methoden und der Unterstützung einiger anderer allgemeiner Dinge.

Mit dem reaktiven Modell erhalten wir jetzt dieselben Methoden und Spezifikationen, außer dass wir die Ergebnisse und Parameter auf reaktive Weise behandeln.

5.1. ReactiveCrudRepository

Wir können dieses Repository genauso verwenden wie das blockierende CrudRepository :

@Repository
public interface AccountCrudRepository 
  extends ReactiveCrudRepository<Account, String> {
 
    Flux<Account> findAllByValue(String value);
    Mono<Account> findFirstByOwner(Mono<String> owner);
}

Wir können verschiedene Arten von Argumenten übergeben, z. B. einfach (String ), verpackt (Optional , Streamen ) oder reaktiv (Mono , Fluss ), wie wir in findFirstByOwner() sehen können Methode.

5.2. ReactiveMongoRepository

Es gibt auch das ReactiveMongoRepository Schnittstelle, die von ReactiveCrudRepository erbt und fügt einige neue Abfragemethoden hinzu:

@Repository
public interface AccountReactiveRepository 
  extends ReactiveMongoRepository<Account, String> { }

Verwenden des ReactiveMongoRepository , können wir beispielsweise abfragen:

Flux<Account> accountFlux = repository
  .findAll(Example.of(new Account(null, "owner", null)));

Als Ergebnis erhalten wir jedes Konto das ist dasselbe wie im übergebenen Beispiel.

Nachdem unsere Repositories erstellt wurden, haben sie bereits Methoden definiert, um einige Datenbankoperationen durchzuführen, die wir nicht implementieren müssen:

Mono<Account> accountMono 
  = repository.save(new Account(null, "owner", 12.3));
Mono<Account> accountMono2 = repository
  .findById("123456");

5.3. RxJava2CrudRepository

Mit RxJava2CrudRepository, wir haben das gleiche Verhalten wie das ReactiveCrudRepository, aber mit den Ergebnissen und Parametertypen von RxJava :

@Repository
public interface AccountRxJavaRepository 
  extends RxJava2CrudRepository<Account, String> {
 
    Observable<Account> findAllByValue(Double value);
    Single<Account> findFirstByOwner(Single<String> owner);
}

5.4. Testen unserer grundlegenden Operationen

Um unsere Repository-Methoden zu testen, verwenden wir den Test-Subscriber:

@Test
public void givenValue_whenFindAllByValue_thenFindAccount() {
    repository.save(new Account(null, "Bill", 12.3)).block();
    Flux<Account> accountFlux = repository.findAllByValue(12.3);

    StepVerifier
      .create(accountFlux)
      .assertNext(account -> {
          assertEquals("Bill", account.getOwner());
          assertEquals(Double.valueOf(12.3) , account.getValue());
          assertNotNull(account.getId());
      })
      .expectComplete()
      .verify();
}

@Test
public void givenOwner_whenFindFirstByOwner_thenFindAccount() {
    repository.save(new Account(null, "Bill", 12.3)).block();
    Mono<Account> accountMono = repository
      .findFirstByOwner(Mono.just("Bill"));

    StepVerifier
      .create(accountMono)
      .assertNext(account -> {
          assertEquals("Bill", account.getOwner());
          assertEquals(Double.valueOf(12.3) , account.getValue());
          assertNotNull(account.getId());
      })
      .expectComplete()
      .verify();
}

@Test
public void givenAccount_whenSave_thenSaveAccount() {
    Mono<Account> accountMono = repository.save(new Account(null, "Bill", 12.3));

    StepVerifier
      .create(accountMono)
      .assertNext(account -> assertNotNull(account.getId()))
      .expectComplete()
      .verify();
}

6. ReactiveMongoTemplate

Neben dem Repositories-Ansatz haben wir das ReactiveMongoTemplate .

Zuerst müssen wir ReactiveMongoTemplate registrieren als Bohne:

@Configuration
public class ReactiveMongoConfig {
 
    @Autowired
    MongoClient mongoClient;

    @Bean
    public ReactiveMongoTemplate reactiveMongoTemplate() {
        return new ReactiveMongoTemplate(mongoClient, "test");
    }
}

Und dann können wir diese Bean in unseren Dienst einfügen, um die Datenbankoperationen auszuführen:

@Service
public class AccountTemplateOperations {
 
    @Autowired
    ReactiveMongoTemplate template;

    public Mono<Account> findById(String id) {
        return template.findById(id, Account.class);
    }
 
    public Flux<Account> findAll() {
        return template.findAll(Account.class);
    } 
    public Mono<Account> save(Mono<Account> account) {
        return template.save(account);
    }
}

ReactiveMongoTemplate hat auch eine Reihe von Methoden, die sich nicht auf die Domäne beziehen, die wir haben, Sie können sie in der Dokumentation nachlesen.