MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Repository Spring Data Reactive con MongoDB

1. Introduzione

In questo tutorial, vedremo come configurare e implementare operazioni di database utilizzando la programmazione reattiva tramite Spring Data Reactive Repositories con MongoDB.

Esamineremo gli utilizzi di base di ReactiveCrud Archivio, ReactiveMongoRepository , così come ReactiveMongoTemplate.

Anche se queste implementazioni utilizzano la programmazione reattiva, questo non è l'obiettivo principale di questo tutorial.

2. Ambiente

Per utilizzare Reactive MongoDB, dobbiamo aggiungere la dipendenza al nostro pom.xml.

Aggiungeremo anche un MongoDB incorporato per il test:

<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. Configurazione

Per attivare il supporto reattivo, dobbiamo utilizzare il @EnableReactiveMongoRepositories insieme ad alcune impostazioni dell'infrastruttura:

@EnableReactiveMongoRepositories
public class MongoReactiveApplication
  extends AbstractReactiveMongoConfiguration {

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

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

Nota che quanto sopra sarebbe necessario se stessimo utilizzando l'installazione autonoma di MongoDB. Tuttavia, poiché nel nostro esempio utilizziamo Spring Boot con MongoDB incorporato, la configurazione sopra non è necessaria.

4. Creazione di un documento

Per gli esempi seguenti, creiamo un Account classe e annotalo con @Document per usarlo nelle operazioni di database:

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

5. Utilizzo di repository reattivi

Abbiamo già familiarità con il modello di programmazione dei repository, con i metodi CRUD già definiti oltre al supporto anche per altre cose comuni.

Ora con il modello reattivo otteniamo lo stesso insieme di metodi e specifiche, tranne per il fatto che tratteremo i risultati e i parametri in modo reattivo.

5.1. ReactiveCrudRepository

Possiamo usare questo repository allo stesso modo del blocco CrudRepository :

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

Possiamo passare diversi tipi di argomenti come plain (String ), avvolto (Facoltativo , Stream ) o reattivo (Mono , Flusso ) come possiamo vedere in findFirstByOwner() metodo.

5.2. ReactiveMongoRepository

C'è anche il ReactiveMongoRepository interfaccia, che eredita da ReactiveCrudRepository e aggiunge alcuni nuovi metodi di query:

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

Utilizzando il ReactiveMongoRepository , possiamo interrogare per esempio:

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

Di conseguenza, otterremo ogni Account è lo stesso dell'esempio passato.

Con i nostri repository creati, hanno già definito metodi per eseguire alcune operazioni sul database che non dobbiamo implementare:

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

5.3. RxJava2CrudRepository

Con RxJava2CrudRepository, abbiamo lo stesso comportamento di ReactiveCrudRepository, ma con i risultati e i tipi di parametri di RxJava :

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

5.4. Testare le nostre operazioni di base

Per testare i nostri metodi di repository, utilizzeremo l'iscritto di test:

@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

Oltre all'approccio dei repository, abbiamo il ReactiveMongoTemplate .

Prima di tutto, dobbiamo registrarci ReactiveMongoTemplate come un fagiolo:

@Configuration
public class ReactiveMongoConfig {
 
    @Autowired
    MongoClient mongoClient;

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

E poi, possiamo iniettare questo bean nel nostro servizio per eseguire le operazioni di database:

@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 ha anche una serie di metodi che non riguardano il dominio che abbiamo, puoi verificarli nella documentazione.