Référentiels réactifs de données de printemps avec MongoDB

Référentiels Spring Data Reactive avec MongoDB

1. introduction

Dans ce didacticiel, nous allons voir comment configurer et implémenter des opérations de base de données à l'aide de la programmation réactive via Spring Data Reactive Repositories avec MongoDB.

Nous allons passer en revue les utilisations de base deReactiveCrudRepository,ReactiveMongoRepository, ainsi que deReactiveMongoTemplate.

Même si ces implémentations utilisentreactive programming, ce n’est pas l’objet principal de ce didacticiel.

2. Environnement

Afin d'utiliser Reactive MongoDB, nous devons ajouter la dépendance à nospom.xml.

Nous allons également ajouter un MongoDB intégré pour les tests:


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

3. Configuration

Afin d'activer le support réactif, nous devons utiliser les@EnableReactiveMongoRepositories avec une configuration d'infrastructure:

@EnableReactiveMongoRepositories
public class MongoReactiveApplication
  extends AbstractReactiveMongoConfiguration {

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

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

Notez que ce qui précède serait nécessaire si nous utilisions l’installation autonome de MongoDB. Mais, comme nous utilisons Spring Boot avec MongoDB intégré dans notre exemple, la configuration ci-dessus n'est pas nécessaire.

4. Créer unDocument

Pour les exemples ci-dessous, créons une classeAccount et annotons-la avec@Document pour l'utiliser dans les opérations de la base de données:

@Document
public class Account {

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

    // getters and setters
}

5. Utilisation de référentiels réactifs

Nous sommes déjà familiers avec lesrepositories programming model, avec les méthodes CRUD déjà définies ainsi que la prise en charge d'autres choses courantes.

Désormais, avec le modèle réactif, nous obtenons le même ensemble de méthodes et de spécifications, sauf que nous traiterons les résultats et les paramètres de manière réactive.

5.1. ReactiveCrudRepository

Nous pouvons utiliser ce référentiel de la même manière que lesCrudRepository bloquants:

@Repository
public interface AccountCrudRepository
  extends ReactiveCrudRepository {

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

Nous pouvons passer différents types d'arguments comme plain (String), enveloppé (Optional,Stream) ou réactif (Mono,Flux) comme nous le pouvons voir dans la méthodefindFirstByOwner().

5.2. ReactiveMongoRepository

Il y a également l'interfaceReactiveMongoRepository, qui hérite deReactiveCrudRepository et ajoute de nouvelles méthodes de requête:

@Repository
public interface AccountReactiveRepository
  extends ReactiveMongoRepository { }

En utilisant lesReactiveMongoRepository, nous pouvons interroger par exemple:

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

En conséquence, nous obtiendrons chaqueAccount identique à l'exemple passé.

Une fois nos référentiels créés, ils ont déjà défini des méthodes pour effectuer certaines opérations de base de données que nous n'avons pas besoin de mettre en œuvre:

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

5.3. RxJava2CrudRepository

AvecRxJava2CrudRepository,, nous avons le même comportement que lesReactiveCrudRepository, mais avec les résultats et les types de paramètres deRxJava:

@Repository
public interface AccountRxJavaRepository
  extends RxJava2CrudRepository {

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

5.4. Tester nos opérations de base

Afin de tester nos méthodes de dépôt, nous utiliserons l'abonné de test:

@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

Outre l'approche des référentiels, nous avons lesReactiveMongoTemplate.

Tout d'abord, nous devons enregistrerReactiveMongoTemplate en tant que bean:

@Configuration
public class ReactiveMongoConfig {

    @Autowired
    MongoClient mongoClient;

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

Et ensuite, nous pouvons injecter ce bean dans notre service pour effectuer les opérations de base de données:

@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 a également un certain nombre de méthodes qui ne sont pas liées au domaine que nous avons, vous pouvez les vérifier dans ledocumentation.

7. Conclusion

Dans ce bref didacticiel, nous avons couvert l'utilisation de référentiels et de modèles à l'aide de la programmation réactive avec MongoDB avec le framework Spring Data Reactive Repositories.

Le code source complet des exemples est disponibleover on GitHub.