MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Référentiels réactifs Spring Data avec MongoDB

1. Présentation

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 passerons en revue les utilisations de base de ReactiveCrud Répertoire, ReactiveMongoRepository , ainsi que ReactiveMongoTemplate.

Même si ces implémentations utilisent la programmation réactive, ce n'est pas l'objectif principal de ce didacticiel.

2. Environnement

Pour utiliser Reactive MongoDB, nous devons ajouter la dépendance à notre pom.xml.

Nous ajouterons également une MongoDB intégrée pour les tests :

<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. Paramétrage

Afin d'activer le support réactif, nous devons utiliser @EnableReactiveMongoRepositories parallèlement à la configuration de l'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éation d'un document

Pour les exemples ci-dessous, créons un compte class et annotez-le avec @Document pour l'utiliser dans les opérations de 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 connaissons déjà le modèle de programmation des référentiels, avec les méthodes CRUD déjà définies ainsi que la prise en charge de certaines autres choses courantes également.

Maintenant, 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 le blocage CrudRepository :

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

Nous pouvons passer différents types d'arguments comme plain (String ), emballé (facultatif , Diffusion ), ou réactif (Mono , flux ) comme nous pouvons le voir dans le findFirstByOwner() méthode.

5.2. ReactiveMongoRepository

Il y a aussi le ReactiveMongoRepository interface, qui hérite de ReactiveCrudRepository et ajoute de nouvelles méthodes de requête :

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

Utiliser le ReactiveMongoRepository , nous pouvons interroger par exemple :

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

En conséquence, nous obtiendrons chaque compte c'est la même chose que 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 d'implémenter :

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

5.3. RxJava2CrudRepository

Avec RxJava2CrudRepository, nous avons le même comportement que le ReactiveCrudRepository, mais avec les résultats et les types de paramètres de RxJava :

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

5.4. Tester nos opérations de base

Afin de tester nos méthodes de référentiel, nous utiliserons l'abonné de 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

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

Tout d'abord, nous devons enregistrer ReactiveMongoTemplate comme un haricot :

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