1. введение
В этом уроке мы рассмотрим, как настроить и реализовать операции с базами данных с помощью реактивного программирования через реактивные хранилища данных Spring с помощью MongoDB.
Мы рассмотрим основные способы использования Reactive Crud Repository, Reactive Mongo Repository , , а также ReactiveMongoTemplate.
Несмотря на то , что эти реализации используют реактивное программирование, это не является основным направлением данного руководства.
2. Окружающая среда
Чтобы использовать реактивный MongoDB, нам нужно добавить зависимость в ваш pom.xml.
Мы также добавим встроенный MongoDB для тестирования:
// ... org.springframework.boot spring-boot-starter-data-mongodb-reactive de.flapdoodle.embed de.flapdoodle.embed.mongo test
3. Конфигурация
Чтобы активировать реактивную поддержку, нам нужно использовать @EnableReactiveMongoRepositories наряду с некоторыми настройками инфраструктуры:
@EnableReactiveMongoRepositories
public class MongoReactiveApplication
extends AbstractReactiveMongoConfiguration {
@Bean
public MongoClient mongoClient() {
return MongoClients.create();
}
@Override
protected String getDatabaseName() {
return "reactive";
}
}Обратите внимание, что вышесказанное было бы необходимо, если бы мы использовали автономную установку MongoDB. Но, поскольку в нашем примере мы используем Spring Boot со встроенным MongoDB, приведенная выше конфигурация не требуется.
4. Создание документа
Для приведенных ниже примеров давайте создадим класс Account и аннотируем его с помощью @Document , чтобы использовать его в операциях с базой данных:
@Document
public class Account {
@Id
private String id;
private String owner;
private Double value;
// getters and setters
}5. Использование реактивных Репозиториев
Мы уже знакомы с моделью программирования репозиториев , с уже определенными методами CRUD, а также с поддержкой некоторых других общих вещей.
Теперь с реактивной моделью мы получаем тот же набор методов и спецификаций, за исключением того, что мы будем иметь дело с результатами и параметрами реактивным способом.
5.1. Реактивная грубая репозиция
Мы можем использовать этот репозиторий так же, как блокирующий CrudRepository :
@Repository public interface AccountCrudRepository extends ReactiveCrudRepository{ Flux findAllByValue(String value); Mono findFirstByOwner(Mono owner); }
Мы можем передавать различные типы аргументов, такие как простые ( String ), обернутые ( Необязательные , Stream ) или реактивные ( Mono , Flux ), как мы видим в методе findFirstByOwner () .
5.2. Реактивный репозиторий Mongo
Существует также интерфейс Reactive Mongo Repository , который наследуется от Reactive CrudRepository и добавляет некоторые новые методы запросов:
@Repository public interface AccountReactiveRepository extends ReactiveMongoRepository{ }
Используя репозиторий Reactive Mongo , мы можем запросить пример:
FluxaccountFlux = repository .findAll(Example.of(new Account(null, "owner", null)));
В результате мы получим каждый Аккаунт , который совпадает с переданным примером.
С созданием наших репозиториев у них уже есть определенные методы для выполнения некоторых операций с базой данных, которые нам не нужно реализовывать:
MonoaccountMono = repository.save(new Account(null, "owner", 12.3)); Mono accountMono2 = repository .findById("123456");
5.3. RxJava2CrudRepository
С RxJava2CrudRepository, мы имеем то же поведение, что и с Реактивным CrudRepository, но с результатами и типами параметров из RxJava :
@Repository public interface AccountRxJavaRepository extends RxJava2CrudRepository{ Observable findAllByValue(Double value); Single findFirstByOwner(Single owner); }
5.4. Тестирование Наших Основных Операций
Чтобы протестировать наши методы репозитория, мы будем использовать тестовый подписчик:
@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. Шаблон ReactiveMongo
Помимо подхода к репозиториям, у нас есть шаблон ReactiveMongo .
Прежде всего, нам нужно зарегистрировать Шаблон ReactiveMongo в качестве боба:
@Configuration
public class ReactiveMongoConfig {
@Autowired
MongoClient mongoClient;
@Bean
public ReactiveMongoTemplate reactiveMongoTemplate() {
return new ReactiveMongoTemplate(mongoClient, "test");
}
}А затем мы можем внедрить этот компонент в наш сервис для выполнения операций с базой данных:
@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);
}
} Шаблон ReactiveMongo также имеет ряд методов, которые не относятся к нашему домену, вы можете проверить их в документации .
7. Заключение
В этом кратком руководстве мы рассмотрели использование репозиториев и шаблонов с использованием реактивного программирования с помощью MongoDB с помощью Spring Data Reactive Repositories framework.
Полный исходный код примеров доступен на GitHub .