sql >> Base de Datos >  >> NoSQL >> MongoDB

Repositorios reactivos de Spring Data con MongoDB

1. Introducción

En este tutorial, veremos cómo configurar e implementar operaciones de base de datos usando Programación Reactiva a través de Spring Data Reactive Repositories con MongoDB.

Repasaremos los usos básicos de ReactiveCrud Repositorio, Repositorio ReactiveMongo , así como ReactiveMongoTemplate.

Aunque estas implementaciones usan programación reactiva, ese no es el enfoque principal de este tutorial.

2. Medio ambiente

Para usar Reactive MongoDB, debemos agregar la dependencia a nuestro pom.xml.

También agregaremos un MongoDB incrustado para probar:

<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. Configuración

Para activar el soporte reactivo, necesitamos usar @EnableReactiveMongoRepositories junto con alguna configuración de infraestructura:

@EnableReactiveMongoRepositories
public class MongoReactiveApplication
  extends AbstractReactiveMongoConfiguration {

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

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

Tenga en cuenta que lo anterior sería necesario si estuviéramos usando la instalación independiente de MongoDB. Pero, como estamos usando Spring Boot con MongoDB integrado en nuestro ejemplo, la configuración anterior no es necesaria.

4. Crear un Documento

Para los ejemplos a continuación, creemos una Cuenta class y anótelo con @Document para usarlo en las operaciones de la base de datos:

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

5. Uso de repositorios reactivos

Ya estamos familiarizados con el modelo de programación de repositorios, con los métodos CRUD ya definidos, además de soporte para algunas otras cosas comunes también.

Ahora, con el modelo Reactivo, obtenemos el mismo conjunto de métodos y especificaciones, excepto que trataremos los resultados y parámetros de forma reactiva.

5.1. Repositorio ReactiveCrud

Podemos usar este repositorio de la misma manera que el bloque CrudRepository :

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

Podemos pasar diferentes tipos de argumentos como simples (String ), envuelto (Opcional , Corriente ), o reactivo (Mono , Flujo ) como podemos ver en findFirstByOwner() método.

5.2. Repositorio ReactiveMongo

También está el ReactiveMongoRepository interfaz, que hereda de ReactiveCrudRepository y agrega algunos nuevos métodos de consulta:

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

Uso del repositorio ReactiveMongo , podemos consultar por ejemplo:

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

Como resultado, obtendremos cada Cuenta eso es lo mismo que el ejemplo pasado.

Con nuestros repositorios creados, ya tienen métodos definidos para realizar algunas operaciones de base de datos que no necesitamos implementar:

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

5.3. Repositorio RxJava2Crud

Con RxJava2CrudRepository, tenemos el mismo comportamiento que el ReactiveCrudRepository, pero con los resultados y tipos de parámetros de RxJava :

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

5.4. Probando Nuestras Operaciones Básicas

Para probar nuestros métodos de repositorio, usaremos el suscriptor de prueba:

@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. Plantilla Reactiva de Mongo

Además del enfoque de repositorios, tenemos la ReactiveMongoTemplate .

En primer lugar, debemos registrar ReactiveMongoTemplate como un frijol:

@Configuration
public class ReactiveMongoConfig {
 
    @Autowired
    MongoClient mongoClient;

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

Y luego, podemos inyectar este bean en nuestro servicio para realizar las operaciones de la base de datos:

@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);
    }
}

Plantilla Reactiva de Mongo también tiene una serie de métodos que no se relacionan con el dominio que tenemos, puede consultarlos en la documentación.