1. Panoramica
A partire dalla versione 4.0, MongoDB supporta transazioni ACID multi-documento. Inoltre, Spring Data Lovelace ora fornisce supporto per queste transazioni MongoDB native .
In questo tutorial parleremo del supporto di Spring Data MongoDB per le transazioni sincrone e reattive.
Daremo anche un'occhiata a Spring Data TransactionTemplate per il supporto delle transazioni non native.
Per un'introduzione a questo modulo Spring Data, dai un'occhiata al nostro articolo introduttivo.
2. Configura MongoDB 4.0
Innanzitutto, dovremo configurare l'ultimo MongoDB per provare il nuovo supporto per le transazioni native.
Per iniziare, dobbiamo scaricare l'ultima versione dal Centro download di MongoDB.
Successivamente, inizieremo mongod servizio utilizzando la riga di comando:
mongod --replSet rs0
Infine, avvia il set di repliche, se non già:
mongo --eval "rs.initiate()"
Nota che MongoDB attualmente supporta le transazioni su un set di repliche.
3. Configurazione Maven
Successivamente, dobbiamo aggiungere le seguenti dipendenze al nostro pom.xml :
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
L'ultima versione della libreria può essere trovata nel Repository Centrale
4. Configurazione MongoDB
Ora, diamo un'occhiata alla nostra configurazione:
@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);
}
}
Tieni presente che dobbiamo registrare MongoTransactionManager nella nostra configurazione per abilitare le transazioni MongoDB native poiché sono disabilitate per impostazione predefinita.
5. Transazioni sincrone
Dopo aver terminato la configurazione, tutto ciò che dobbiamo fare per utilizzare le transazioni MongoDB native è annotare il nostro metodo con @Transazionale .
Tutto all'interno del metodo annotato verrà eseguito in un'unica transazione:
@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));
}
Tieni presente che non possiamo utilizzare listCollections comando all'interno di una transazione multi-documento, ad esempio:
@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));
}
}
Questo esempio genera una MongoTransactionException poiché abbiamo usato la collectionExists() metodo.
6. Modello di transazione
Abbiamo visto come Spring Data supporta la nuova transazione nativa MongoDB. Inoltre, Spring Data fornisce anche l'opzione non nativa.
Possiamo eseguire transazioni non native utilizzando 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));
}
Dobbiamo impostare SessionSynchronization a SEMPRE per utilizzare transazioni Spring Data non native.
7. Transazioni reattive
Infine, daremo un'occhiata al supporto Spring Data per le transazioni reattive MongoDB .
Dovremo aggiungere altre dipendenze a pom.xml per lavorare con MongoDB reattivo:
<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>
Le dipendenze mongodb-driver-reactivestreams, mongodb-driver-sync e reactor-test sono disponibili su Maven Central.
E, naturalmente, dobbiamo configurare il nostro MongoDB reattivo:
@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";
}
}
Per utilizzare le transazioni in MongoDB reattivo, dobbiamo usare inTransaction() metodo in 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)));
}
Maggiori informazioni sui repository reattivi in Spring Data sono disponibili qui.