MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Transazioni di dati di primavera MongoDB

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.