Repositórios reativos de dados da primavera com o MongoDB

Repositórios reativos de dados da primavera com o MongoDB

1. Introdução

Neste tutorial, veremos como configurar e implementar operações de banco de dados usando programação reativa por meio de repositórios reativos Spring Data com MongoDB.

Veremos os usos básicos deReactiveCrudRepository,ReactiveMongoRepository,, bem comoReactiveMongoTemplate.

Mesmo que essas implementações usemreactive programming, esse não é o foco principal deste tutorial.

2. Meio Ambiente

Para usar o MongoDB reativo, precisamos adicionar a dependência ao nossopom.xml.

Também adicionaremos um MongoDB incorporado para teste:


    // ...
    
        org.springframework.boot
        spring-boot-starter-data-mongodb-reactive
    
    
        de.flapdoodle.embed
        de.flapdoodle.embed.mongo
        test
    

3. Configuração

Para ativar o suporte reativo, precisamos usar@EnableReactiveMongoRepositories juntamente com alguma configuração de infraestrutura:

@EnableReactiveMongoRepositories
public class MongoReactiveApplication
  extends AbstractReactiveMongoConfiguration {

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

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

Observe que o acima seria necessário se estivéssemos usando a instalação independente do MongoDB. Mas, como estamos usando Spring Boot com MongoDB incorporado em nosso exemplo, a configuração acima não é necessária.

4. Criando umDocument

Para os exemplos abaixo, vamos criar uma classeAccount e anotar com@Document para usá-la nas operações do banco de dados:

@Document
public class Account {

    @Id
    private String id;
    private String owner;
    private Double value;

    // getters and setters
}

5. Usando Repositórios Reativos

Já estamos familiarizados com orepositories programming model, com os métodos CRUD já definidos, além do suporte para algumas outras coisas comuns também.

Agora, com o modelo reativo, obtemos o mesmo conjunto de métodos e especificações, exceto que lidaremos com os resultados e parâmetros de uma forma reativa.

5.1. ReactiveCrudRepository

Podemos usar este repositório da mesma forma que o bloqueioCrudRepository:

@Repository
public interface AccountCrudRepository
  extends ReactiveCrudRepository {

    Flux findAllByValue(String value);
    Mono findFirstByOwner(Mono owner);
}

Podemos passar diferentes tipos de argumentos como simples (String), empacotados (Optional,Stream) ou reativos (Mono,Flux), conforme podemos veja no métodofindFirstByOwner().

5.2. ReactiveMongoRepository

Há também a interfaceReactiveMongoRepository, que herda deReactiveCrudRepository e adiciona alguns novos métodos de consulta:

@Repository
public interface AccountReactiveRepository
  extends ReactiveMongoRepository { }

UsandoReactiveMongoRepository, podemos consultar por exemplo:

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

Como resultado, obteremos cadaAccount igual ao exemplo passado.

Com nossos repositórios criados, eles já definiram métodos para realizar algumas operações de banco de dados que não precisamos implementar:

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

5.3. RxJava2CrudRepository

ComRxJava2CrudRepository,, temos o mesmo comportamento queReactiveCrudRepository,, mas com os resultados e tipos de parâmetro deRxJava:

@Repository
public interface AccountRxJavaRepository
  extends RxJava2CrudRepository {

    Observable findAllByValue(Double value);
    Single findFirstByOwner(Single owner);
}

5.4. Testando Nossas Operações Básicas

Para testar nossos métodos de repositório, usaremos o assinante de teste:

@Test
public void givenValue_whenFindAllByValue_thenFindAccount() {
    repository.save(new Account(null, "Bill", 12.3)).block();
    Flux 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 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 accountMono = repository.save(new Account(null, "Bill", 12.3));

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

6. ReactiveMongoTemplate

Além da abordagem de repositórios, temos oReactiveMongoTemplate.

Em primeiro lugar, precisamos registrarReactiveMongoTemplate como um bean:

@Configuration
public class ReactiveMongoConfig {

    @Autowired
    MongoClient mongoClient;

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

E então, podemos injetar esse bean em nosso serviço para executar as operações do banco de dados:

@Service
public class AccountTemplateOperations {

    @Autowired
    ReactiveMongoTemplate template;

    public Mono findById(String id) {
        return template.findById(id, Account.class);
    }

    public Flux findAll() {
        return template.findAll(Account.class);
    }
    public Mono save(Mono account) {
        return template.save(account);
    }
}

ReactiveMongoTemplate também tem uma série de métodos que não se relacionam ao domínio que temos, você pode verificá-los emdocumentation.

7. Conclusão

Neste breve tutorial, cobrimos o uso de repositórios e modelos usando programação reativa com MongoDB com estrutura Spring Data Reactive Repositories.

O código-fonte completo dos exemplos está disponívelover on GitHub.