1. Pendahuluan
Dalam tutorial ini, kita akan melihat cara mengonfigurasi dan mengimplementasikan operasi database menggunakan Pemrograman Reaktif melalui Spring Data Reactive Repositories dengan MongoDB.
Kami akan membahas penggunaan dasar ReactiveCrud Repositori, ReactiveMongoRepository , serta ReactiveMongoTemplate.
Meskipun implementasi ini menggunakan pemrograman reaktif, itu bukan fokus utama dari tutorial ini.
2. Lingkungan
Untuk menggunakan Reactive MongoDB, kita perlu menambahkan dependensi ke pom.xml. kita.
Kami juga akan menambahkan MongoDB yang disematkan untuk pengujian:
<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. Konfigurasi
Untuk mengaktifkan dukungan reaktif, kita perlu menggunakan @EnableReactiveMongoRepositories bersama dengan beberapa penyiapan infrastruktur:
@EnableReactiveMongoRepositories
public class MongoReactiveApplication
extends AbstractReactiveMongoConfiguration {
@Bean
public MongoClient mongoClient() {
return MongoClients.create();
}
@Override
protected String getDatabaseName() {
return "reactive";
}
}
Perhatikan bahwa hal di atas akan diperlukan jika kita menggunakan instalasi MongoDB mandiri. Namun, karena kami menggunakan Spring Boot dengan MongoDB tersemat dalam contoh kami, konfigurasi di atas tidak diperlukan.
4. Membuat Dokumen
Untuk contoh di bawah ini, mari buat Akun kelas dan beri anotasi dengan @Document untuk menggunakannya dalam operasi database:
@Document
public class Account {
@Id
private String id;
private String owner;
private Double value;
// getters and setters
}
5. Menggunakan Repositori Reaktif
Kita sudah akrab dengan model pemrograman repositori, dengan metode CRUD yang sudah ditentukan ditambah dukungan untuk beberapa hal umum lainnya juga.
Sekarang dengan model Reactive, kita mendapatkan kumpulan metode dan spesifikasi yang sama, kecuali bahwa kita akan menangani hasil dan parameter dengan cara reaktif.
5.1. ReactiveCrudRepository
Kita dapat menggunakan repositori ini dengan cara yang sama seperti memblokir CrudRepository :
@Repository
public interface AccountCrudRepository
extends ReactiveCrudRepository<Account, String> {
Flux<Account> findAllByValue(String value);
Mono<Account> findFirstByOwner(Mono<String> owner);
}
Kita dapat melewatkan berbagai jenis argumen seperti plain (String ), dibungkus (Opsional , Aliran ), atau reaktif (Mono , Fluks ) seperti yang bisa kita lihat di findFirstByOwner() metode.
5.2. ReactiveMongoRepository
Ada juga ReactiveMongoRepository antarmuka, yang mewarisi dari ReactiveCrudRepository dan menambahkan beberapa metode kueri baru:
@Repository
public interface AccountReactiveRepository
extends ReactiveMongoRepository<Account, String> { }
Menggunakan ReactiveMongoRepository , kita dapat melakukan query dengan contoh:
Flux<Account> accountFlux = repository
.findAll(Example.of(new Account(null, "owner", null)));
Hasilnya, kami akan mendapatkan setiap Akun itu sama dengan contoh yang diberikan.
Dengan repositori kami dibuat, mereka sudah memiliki metode yang ditentukan untuk melakukan beberapa operasi basis data yang tidak perlu kami implementasikan:
Mono<Account> accountMono
= repository.save(new Account(null, "owner", 12.3));
Mono<Account> accountMono2 = repository
.findById("123456");
5.3. RxJava2CrudRepository
Dengan RxJava2CrudRepository, kami memiliki perilaku yang sama dengan ReactiveCrudRepository, tetapi dengan hasil dan tipe parameter dari RxJava :
@Repository
public interface AccountRxJavaRepository
extends RxJava2CrudRepository<Account, String> {
Observable<Account> findAllByValue(Double value);
Single<Account> findFirstByOwner(Single<String> owner);
}
5.4. Menguji Operasi Dasar Kami
Untuk menguji metode repositori kami, kami akan menggunakan pelanggan uji:
@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
Selain pendekatan repositori, kami memiliki ReactiveMongoTemplate .
Pertama-tama, kita perlu mendaftar ReactiveMongoTemplate sebagai kacang:
@Configuration
public class ReactiveMongoConfig {
@Autowired
MongoClient mongoClient;
@Bean
public ReactiveMongoTemplate reactiveMongoTemplate() {
return new ReactiveMongoTemplate(mongoClient, "test");
}
}
Dan kemudian, kami dapat menyuntikkan kacang ini ke dalam layanan kami untuk melakukan operasi basis data:
@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 juga memiliki sejumlah metode yang tidak terkait dengan domain yang kami miliki, Anda dapat memeriksanya di dokumentasi.