MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Transactions MongoDB Spring Data

1. Présentation

À partir de la version 4.0, MongoDB prend en charge les transactions ACID multi-documents. Et, Spring Data Lovelace prend désormais en charge ces transactions MongoDB natives .

Dans ce didacticiel, nous aborderons la prise en charge de Spring Data MongoDB pour les transactions synchrones et réactives.

Nous allons également jeter un œil à Spring Data TransactionTemplate pour la prise en charge des transactions non natives.

Pour une introduction à ce module Spring Data, consultez notre article d'introduction.

2. Configurer MongoDB 4.0

Tout d'abord, nous devrons 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 le centre de téléchargement MongoDB.

Ensuite, nous allons commencer mongod service à l'aide de la ligne de commande :

mongod --replSet rs0

Enfin, lancez le jeu de répliques - 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épliques.

3. Configuration Maven

Ensuite, nous devons ajouter les dépendances suivantes à notre pom.xml :

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-mongodb</artifactId>
    <version>3.0.3.RELEASE</version>
</dependency>

La dernière version de la bibliothèque se trouve sur le référentiel central

4. Configuration de MongoDB

Voyons maintenant notre configuration :

@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);
    }
}

Notez que nous devons enregistrer MongoTransactionManager dans notre configuration pour 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 avons à faire pour utiliser les transactions MongoDB natives est d'annoter notre méthode avec @Transactionnel .

Tout ce qui se trouve dans la méthode annotée sera exécuté en une seule 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<User> users = mongoTemplate.find(query, User.class);

    assertThat(users.size(), is(1));
}

Notez que nous ne pouvons pas utiliser listCollections commande à l'intérieur d'une transaction multi-documents - 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 lève une MongoTransactionException comme nous avons utilisé le collectionExists() méthode.

6. Modèle de transaction

Nous avons vu comment Spring Data prend en charge la nouvelle transaction native MongoDB. De plus, Spring Data fournit également l'option non native.

Nous pouvons effectuer des transactions non natives à l'aide de 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));
}

Nous devons définir SessionSynchronization à TOUJOURS pour utiliser des transactions Spring Data non natives.

7. Transactions réactives

Enfin, nous examinerons la prise en charge de Spring Data pour les transactions réactives MongoDB .

Nous devrons ajouter quelques dépendances supplémentaires au pom.xml pour travailler avec MongoDB réactif :

<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>

Les dépendances mongodb-driver-reactivestreams, mongodb-driver-sync et reacteur-test sont disponibles sur Maven Central.

Et bien sûr, nous devons configurer notre MongoDB réactif :

@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";
    }
}

Pour utiliser les transactions dans MongoDB réactif, nous devons utiliser le inTransaction() méthode dans 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)));
}

Plus d'informations sur les référentiels réactifs dans Spring Data sont disponibles ici.