Перейти к основному содержимому

Транзакции Spring Data MongoDB

· 4 мин. чтения

Упражнение: Сложение двух чисел

Даны два неотрицательный целых числа в виде непустых связных списков. Их цифры хранятся в обратном порядке. И каждый елемент списка содержить ровно одну цифру. Сложите эти два числа и верните сумму в виде связного списка ...

ANDROMEDA

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.foreach.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. Шаблон транзакции

Мы увидели, как 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.foreach.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 доступна здесь .

8. Заключение

В этой статье мы узнали, как использовать собственные и нестандартные транзакции MongoDB с использованием Spring Data.

Полный исходный код примеров доступен на GitHub.