1. Przegląd
Począwszy od wersji 4.0 MongoDB obsługuje wielodokumentowe transakcje ACID. I Spring Data Lovelace zapewnia teraz obsługę tych natywnych transakcji MongoDB .
W tym samouczku omówimy obsługę Spring Data MongoDB dla transakcji synchronicznych i reaktywnych.
Przyjrzymy się również Spring Data TransactionTemplate do obsługi transakcji innych niż natywne.
Aby zapoznać się z wprowadzeniem do tego modułu Spring Data, zapoznaj się z naszym wstępnym opisem.
2. Skonfiguruj MongoDB 4.0
Najpierw musimy skonfigurować najnowszą bazę danych MongoDB, aby wypróbować nową obsługę transakcji natywnych.
Aby rozpocząć, musimy pobrać najnowszą wersję z Centrum pobierania MongoDB.
Następnie zaczniemy mongod usługa za pomocą wiersza poleceń:
mongod --replSet rs0
Na koniec zainicjuj zestaw replik — jeśli jeszcze nie:
mongo --eval "rs.initiate()"
Zwróć uwagę, że MongoDB obecnie obsługuje transakcje na zestawie replik.
3. Konfiguracja Maven
Następnie musimy dodać następujące zależności do naszego pom.xml :
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
Najnowszą wersję biblioteki można znaleźć w Centralnym Repozytorium
4. Konfiguracja MongoDB
Przyjrzyjmy się teraz naszej konfiguracji:
@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);
}
}
Pamiętaj, że musimy zarejestrować MongoTransactionManager w naszej konfiguracji, aby włączyć natywne transakcje MongoDB, ponieważ są one domyślnie wyłączone.
5. Transakcje synchroniczne
Po zakończeniu konfiguracji wszystko, co musimy zrobić, aby korzystać z natywnych transakcji MongoDB – to opisać naszą metodę za pomocą @Transakcyjne .
Wszystko w opisanej metodzie zostanie wykonane w jednej transakcji:
@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));
}
Pamiętaj, że nie możemy używać listCollections polecenie wewnątrz transakcji wielodokumentowej – na przykład:
@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));
}
}
Ten przykład rzuca MongoTransactionException ponieważ użyliśmy metody collectionExists() metoda.
6. Szablon transakcji
Widzieliśmy, jak Spring Data obsługuje nową transakcję natywną MongoDB. Dodatkowo Spring Data zapewnia również opcję nienatywną.
Możemy przeprowadzać transakcje inne niż natywne za pomocą 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));
}
Musimy ustawić SessionSynchronization do ZAWSZE używać nienatywnych transakcji Spring Data.
7. Transakcje reaktywne
Na koniec przyjrzymy się obsłudze Spring Data dla reaktywnych transakcji MongoDB .
Musimy dodać kilka dodatkowych zależności do pliku pom.xml do pracy z reaktywnym 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>
Zależności mongodb-driver-reactivestreams, mongodb-driver-sync i reaktor-test są dostępne w Maven Central.
I oczywiście musimy skonfigurować naszą reaktywną 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";
}
}
Aby używać transakcji w reaktywnej MongoDB, musimy użyć inTransaction() metoda w 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)));
}
Więcej informacji na temat reaktywnych repozytoriów w Spring Data jest dostępnych tutaj.