Spring Data MongoDB Transactions
1. Vue d'ensemble
À partir de la version 4.0, MongoDB prend en charge les transactions ACID multi-documents. Et,Spring Data Lovelace now provides support for these native MongoDB transactions.
Dans ce didacticiel, nous aborderons la prise en charge de Spring Data MongoDB pour les transactions synchrones et réactives.
Nous examinerons également Spring DataTransactionTemplate pour la prise en charge des transactions non natives.
Pour une introduction à ce module Spring Data, jetez un œil à nosintroductory write-up.
2. Configurer MongoDB 4.0
Tout d'abord, nous devons configurer la dernière version de MongoDB pour essayer la nouvelle prise en charge des transactions natives.
Pour commencer, nous devons télécharger la dernière version depuis leMongoDB Download Center.
Ensuite, nous allons démarrer le servicemongod en utilisant la ligne de commande:
mongod --replSet rs0
Enfin, lancez le jeu de réplicas - si ce n'est déjà fait:
mongo --eval "rs.initiate()"
Notez que MongoDB prend actuellement en charge les transactions sur un jeu de réplicas.
3. Configuration Maven
Ensuite, nous devons ajouter les dépendances suivantes à nospom.xml:
org.springframework.data
spring-data-mongodb
2.1.0.RELEASE
org.springframework.data
spring-data-releasetrain
Lovelace-M3
pom
import
Notez que nous devons également ajouter le référentiel de jalons à nospom.xml:
spring-milestones
Spring Milestones
https://repo.spring.io/milestone
false
La dernière version de la bibliothèque est disponible sur leCentral Repository
4. Configuration de MongoDB
Voyons maintenant notre configuration:
@Configuration
@EnableMongoRepositories(basePackages = "com.example.repository")
public class MongoTransactionConfig extends AbstractMongoConfiguration{
@Bean
MongoTransactionManager transactionManager(MongoDbFactory dbFactory) {
return new MongoTransactionManager(dbFactory);
}
@Override
protected String getDatabaseName() {
return "test";
}
@Override
public MongoClient mongoClient() {
return new MongoClient("127.0.0.1", 27017);
}
}
Notez quewe need to register MongoTransactionManager dans notre configuration permet d'activer les transactions MongoDB natives car elles sont désactivées par défaut.
5. Transactions synchrones
Une fois la configuration terminée, tout ce que nous devons faire pour utiliser les transactions MongoDB natives est deannotate our method with*@Transactional*.
Tout ce qui se trouve dans la méthode annotée sera exécuté dans une transaction:
@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 users = mongoTemplate.find(query, User.class);
assertThat(users.size(), is(1));
}
Notez que nous ne pouvons pas utiliser la commandelistCollections dans une transaction multi-document - par exemple:
@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));
}
}
Cet exemple lance unMongoTransactionException car nous avons utilisé la méthodecollectionExists().
Nous ne pouvons pas non plus exécutercount dans une transaction multi-document:
@Test(expected = MongoCommandException.class)
@Transactional
public void whenCountDuringMongoTransaction_thenException() {
userRepository.save(new User("John", 30));
userRepository.save(new User("Ringo", 35));
userRepository.count();
}
Mais nous pouvons contourner celle-ci avec une requête simple, puis obtenir la taille de la liste résultante:
@Test
@Transactional
public void whenQueryDuringMongoTransaction_thenSuccess() {
userRepository.save(new User("Jane", 20));
userRepository.save(new User("Nick", 33));
List users = mongoTemplate.find(new Query(), User.class);
assertTrue(users.size() > 1);
}
6. TransactionTemplate
Nous avons vu comment Spring Data prend en charge la nouvelle transaction native MongoDB. De plus, Spring Data fournit également l'option non native.
We can perform non-native transactions using 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 users = mongoTemplate.find(query, User.class);
assertThat(users.size(), is(1));
}
Nous devons définirSessionSynchronization surALWAYS pour utiliser des transactions Spring Data non natives.
7. Transactions réactives
Enfin, nous allons jeter un œil àSpring Data support for MongoDB reactive transactions.
Nous devrons ajouter quelques dépendances supplémentaires auxpom.xml pour travailler avec MongoDB réactif:
org.mongodb
mongodb-driver-reactivestreams
1.9.2
io.projectreactor
reactor-test
3.2.0.RELEASE
test
Les dépendancesmongodb-driver-reactivestreams etreactor-test sont disponibles sur Maven Central.
Et bien sûr, nous devons configurer notre MongoDB réactif:
@Configuration
@EnableReactiveMongoRepositories(basePackages
= "com.example.reactive.repository")
public class MongoReactiveConfig
extends AbstractReactiveMongoConfiguration {
@Override
public MongoClient reactiveMongoClient() {
return MongoClients.create();
}
@Override
protected String getDatabaseName() {
return "reactive";
}
}
Pour utiliser des transactions dans MongoDB réactif, nous devons utiliser la méthodeinTransaction() dansReactiveMongoOperations:
@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)));
}
Plus d'informations sur les référentiels réactifs dans Spring Data sont disponibleshere.
8. Conclusion
Dans cet article, nous avons appris à utiliser des transactions MongoDB natives et non natives à l'aide de Spring Data.
Le code source complet des exemples est disponibleover on GitHub.