MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Spring Data MongoDB-Transaktionen

1. Übersicht

Ab Version 4.0 unterstützt MongoDB ACID-Transaktionen mit mehreren Dokumenten. Und Spring Data Lovelace bietet jetzt Unterstützung für diese nativen MongoDB-Transaktionen .

In diesem Tutorial besprechen wir die Spring Data MongoDB-Unterstützung für synchrone und reaktive Transaktionen.

Wir werfen auch einen Blick auf Spring Data TransactionTemplate für die Unterstützung nicht-nativer Transaktionen.

Eine Einführung in dieses Spring Data-Modul finden Sie in unserem Einführungsartikel.

2. MongoDB 4.0 einrichten

Zuerst müssen wir die neueste MongoDB einrichten, um die neue native Transaktionsunterstützung auszuprobieren.

Um zu beginnen, müssen wir die neueste Version aus dem MongoDB Download Center herunterladen.

Als nächstes starten wir mongod Dienst über die Befehlszeile:

mongod --replSet rs0

Abschließend Replica Set initiieren – falls noch nicht geschehen:

mongo --eval "rs.initiate()"

Beachten Sie, dass MongoDB derzeit Transaktionen über einen Replikatsatz unterstützt.

3. Maven-Konfiguration

Als nächstes müssen wir unserer pom.xml die folgenden Abhängigkeiten hinzufügen :

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

Die neueste Version der Bibliothek finden Sie im Central Repository

4. MongoDB-Konfiguration

Werfen wir nun einen Blick auf unsere Konfiguration:

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

Beachten Sie, dass wir MongoTransactionManager registrieren müssen in unserer Konfiguration, um native MongoDB-Transaktionen zu aktivieren, da sie standardmäßig deaktiviert sind.

5. Synchrone Transaktionen

Nachdem wir die Konfiguration abgeschlossen haben, müssen wir nur noch native MongoDB-Transaktionen verwenden – unsere Methode mit kommentieren @Transaktional .

Alles innerhalb der annotierten Methode wird in einer Transaktion ausgeführt:

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

Beachten Sie, dass wir listCollections nicht verwenden können Befehl innerhalb einer Transaktion mit mehreren Dokumenten – zum Beispiel:

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

Dieses Beispiel löst eine MongoTransactionException aus wie wir die collectionExists() verwendet haben Methode.

6. Transaktionsvorlage

Wir haben gesehen, wie Spring Data die neue MongoDB-native Transaktion unterstützt. Darüber hinaus bietet Spring Data auch die nicht-native Option.

Wir können nicht-native Transaktionen mit Spring Data TransactionTemplate durchführen :

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

Wir müssen SessionSynchronization einstellen zu IMMER um nicht native Spring Data-Transaktionen zu verwenden.

7. Reaktive Transaktionen

Abschließend werfen wir einen Blick auf die Spring Data-Unterstützung für reaktive MongoDB-Transaktionen .

Wir müssen der pom.xml einige weitere Abhängigkeiten hinzufügen um mit reaktiver MongoDB zu arbeiten:

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

Die mongodb-driver-reactivestreams-, mongodb-driver-sync- und Reactor-test-Abhängigkeiten sind auf Maven Central verfügbar.

Und natürlich müssen wir unsere reaktive MongoDB konfigurieren:

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

Um Transaktionen in reaktiver MongoDB zu verwenden, müssen wir inTransaction() verwenden -Methode 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)));
}

Weitere Informationen zu reaktiven Repositorys in Spring Data finden Sie hier.