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.