1. Úvod
V tomto tutoriálu se podíváme na to, jak nakonfigurovat a implementovat databázové operace pomocí reaktivního programování prostřednictvím Spring Data Reactive Repositories s MongoDB.
Projdeme si základní použití ReactiveCrud Úložiště, ReactiveMongoRepository , a také ReactiveMongoTemplate.
I když tyto implementace používají reaktivní programování, není to hlavním cílem tohoto tutoriálu.
2. Prostředí
Abychom mohli používat Reactive MongoDB, musíme přidat závislost do našeho pom.xml.
Přidáme také vložený MongoDB pro testování:
<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. Konfigurace
Abychom aktivovali reaktivní podporu, musíme použít @EnableReactiveMongoRepositories spolu s nastavením infrastruktury:
@EnableReactiveMongoRepositories
public class MongoReactiveApplication
extends AbstractReactiveMongoConfiguration {
@Bean
public MongoClient mongoClient() {
return MongoClients.create();
}
@Override
protected String getDatabaseName() {
return "reactive";
}
}
Všimněte si, že výše uvedené by bylo nutné, pokud bychom používali samostatnou instalaci MongoDB. Ale protože v našem příkladu používáme Spring Boot s vloženým MongoDB, výše uvedená konfigurace není nutná.
4. Vytvoření dokumentu
Pro příklady níže si vytvořte účet třídy a označte jej pomocí @Document pro použití v databázových operacích:
@Document
public class Account {
@Id
private String id;
private String owner;
private Double value;
// getters and setters
}
5. Používání reaktivních repozitářů
Již jsme obeznámeni s modelem programování repozitářů, s již definovanými metodami CRUD plus podporou některých dalších běžných věcí.
Nyní s modelem Reactive získáme stejnou sadu metod a specifikací, kromě toho, že s výsledky a parametry budeme pracovat reaktivním způsobem.
5.1. ReactiveCrudRepository
Toto úložiště můžeme použít stejným způsobem jako blokovací CrudRepository :
@Repository
public interface AccountCrudRepository
extends ReactiveCrudRepository<Account, String> {
Flux<Account> findAllByValue(String value);
Mono<Account> findFirstByOwner(Mono<String> owner);
}
Můžeme předávat různé typy argumentů, jako je prostý (String ), zabalené (Volitelné , Stream ), nebo reaktivní (Mono , Flux ), jak můžeme vidět v findFirstByOwner() metoda.
5.2. ReactiveMongoRepository
K dispozici je také ReactiveMongoRepository rozhraní, které dědí z ReactiveCrudRepository a přidává některé nové metody dotazu:
@Repository
public interface AccountReactiveRepository
extends ReactiveMongoRepository<Account, String> { }
Pomocí ReactiveMongoRepository , můžeme se zeptat například:
Flux<Account> accountFlux = repository
.findAll(Example.of(new Account(null, "owner", null)));
V důsledku toho získáme každý účet to je stejné jako v předchozím příkladu.
S našimi vytvořenými repozitáři již mají definované metody pro provádění některých databázových operací, které nemusíme implementovat:
Mono<Account> accountMono
= repository.save(new Account(null, "owner", 12.3));
Mono<Account> accountMono2 = repository
.findById("123456");
5.3. RxJava2CrudRepository
S RxJava2CrudRepository máme stejné chování jako ReactiveCrudRepository ale s výsledky a typy parametrů z RxJava :
@Repository
public interface AccountRxJavaRepository
extends RxJava2CrudRepository<Account, String> {
Observable<Account> findAllByValue(Double value);
Single<Account> findFirstByOwner(Single<String> owner);
}
5.4. Testování našich základních operací
Abychom otestovali naše metody úložiště, použijeme testovacího předplatitele:
@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
Kromě přístupu repozitářů mámeReactiveMongoTemplate .
Nejprve se musíme zaregistrovat ReactiveMongoTemplate jako fazole:
@Configuration
public class ReactiveMongoConfig {
@Autowired
MongoClient mongoClient;
@Bean
public ReactiveMongoTemplate reactiveMongoTemplate() {
return new ReactiveMongoTemplate(mongoClient, "test");
}
}
A pak můžeme vložit tento bean do naší služby, abychom provedli databázové operace:
@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 má také řadu metod, které se nevztahují k naší doméně, můžete si je ověřit v dokumentaci.