1. Прегледа
Започвайки от версия 4.0, MongoDB поддържа многодокументни ACID транзакции. И Spring Data Lovelace вече предоставя поддръжка за тези собствени транзакции на MongoDB .
В този урок ще обсъдим поддръжката на Spring Data MongoDB за синхронни и реактивни транзакции.
Ще разгледаме и Spring Data TransactionTemplate за поддръжка на транзакции, които не са местни.
За въведение в този модул Spring Data, разгледайте нашия уводен текст.
2. Настройте MongoDB 4.0
Първо, ще трябва да настроим най-новата MongoDB, за да изпробваме новата поддръжка за транзакции.
За да започнем, трябва да изтеглим най-новата версия от Центъра за изтегляне на MongoDB.
След това ще започнем mongod услуга с помощта на командния ред:
mongod --replSet rs0
И накрая, стартирайте набор от реплики – ако все още не е:
mongo --eval "rs.initiate()"
Имайте предвид, че MongoDB в момента поддържа транзакции през набор от реплики.
3. Конфигурация на Mavenа
След това трябва да добавим следните зависимости към нашия pom.xml :
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
Най-новата версия на библиотеката може да бъде намерена в Централното хранилище
4. Конфигурация на MongoDBа
Сега, нека да разгледаме нашата конфигурация:
@Configuration
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
public class MongoConfig extends AbstractMongoClientConfiguration{
@Bean
MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
return new MongoTransactionManager(dbFactory);
}
@Override
protected String getDatabaseName() {
return "test";
}
@Override
public MongoClient mongoClient() {
final ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/test");
final MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
.applyConnectionString(connectionString)
.build();
return MongoClients.create(mongoClientSettings);
}
}
Имайте предвид, че трябва да регистрираме MongoTransactionManager в нашата конфигурация, за да активирате собствените транзакции на MongoDB, тъй като те са деактивирани по подразбиране.
5. Синхронни транзакции
След като завършихме конфигурацията, всичко, което трябва да направим, за да използваме собствени транзакции на MongoDB – е да анотираме нашия метод с @Transactional .
Всичко в анотирания метод ще бъде изпълнено в една транзакция:
@Test
@Transactional
public void whenPerformMongoTransaction_thenSuccess() {
userRepository.save(new User("John", 30));
userRepository.save(new User("Ringo", 35));
Query query = new Query().addCriteria(Criteria.where("name").is("John"));
List<User> users = mongoTemplate.find(query, User.class);
assertThat(users.size(), is(1));
}
Имайте предвид, че не можем да използваме listCollections команда в транзакция с множество документи – например:
@Test(expected = MongoTransactionException.class)
@Transactional
public void whenListCollectionDuringMongoTransaction_thenException() {
if (mongoTemplate.collectionExists(User.class)) {
mongoTemplate.save(new User("John", 30));
mongoTemplate.save(new User("Ringo", 35));
}
}
Този пример хвърля MongoTransactionException тъй като използвахме collectionExists() метод.
6. TransactionTemplate
Видяхме как Spring Data поддържат нова собствена транзакция на MongoDB. Освен това Spring Data предоставя и опцията, която не е местна.
Можем да извършваме транзакции, които не са местни с помощта на Spring Data TransactionTemplate :
@Test
public void givenTransactionTemplate_whenPerformTransaction_thenSuccess() {
mongoTemplate.setSessionSynchronization(SessionSynchronization.ALWAYS);
TransactionTemplate transactionTemplate = new TransactionTemplate(mongoTransactionManager);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
mongoTemplate.insert(new User("Kim", 20));
mongoTemplate.insert(new User("Jack", 45));
};
});
Query query = new Query().addCriteria(Criteria.where("name").is("Jack"));
List<User> users = mongoTemplate.find(query, User.class);
assertThat(users.size(), is(1));
}
Трябва да зададем SessionSynchronization до ВИНАГИ за да използвате не-родни транзакции на Spring Data.
7. Реактивни транзакциии
И накрая, ще разгледаме Поддръжката на Spring Data за реактивни транзакции на MongoDB .
Ще трябва да добавим още няколко зависимости към pom.xml за работа с реактивен MongoDB:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-reactivestreams</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.0.5</version>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<version>3.2.0.RELEASE</version>
<scope>test</scope>
</dependency>
Зависимостите mongodb-driver-reactivestreams, mongodb-driver-sync и reactor-test са налични в Maven Central.
И разбира се, трябва да конфигурираме нашия Reactive MongoDB:
@Configuration
@EnableReactiveMongoRepositories(basePackages
= "com.baeldung.reactive.repository")
public class MongoReactiveConfig
extends AbstractReactiveMongoConfiguration {
@Override
public MongoClient reactiveMongoClient() {
return MongoClients.create();
}
@Override
protected String getDatabaseName() {
return "reactive";
}
}
За да използваме транзакции в реактивна MongoDB, трябва да използваме inTransaction() метод в ReactiveMongoOperations :
@Autowired
private ReactiveMongoOperations reactiveOps;
@Test
public void whenPerformTransaction_thenSuccess() {
User user1 = new User("Jane", 23);
User user2 = new User("John", 34);
reactiveOps.inTransaction()
.execute(action -> action.insert(user1)
.then(action.insert(user2)));
}
Повече информация за реактивните хранилища в Spring Data е налична тук.