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.