Spring Data MongoDB-Transaktionen

Spring Data MongoDB-Transaktionen

1. Überblick

Ab der Version 4.0 unterstützt MongoDB ACID-Transaktionen mit mehreren Dokumenten. UndSpring Data Lovelace now provides support for these native MongoDB transactions.

In diesem Lernprogramm wird die Unterstützung von Spring Data MongoDB für synchrone und reaktive Transaktionen erläutert.

Wir werden uns auch Spring DataTransactionTemplatefür die Unterstützung nicht nativer Transaktionen ansehen.

Eine Einführung in dieses Spring Data-Modul finden Sie in unserenintroductory write-up.

2. Richten Sie MongoDB 4.0 ein

Zunächst müssen wir die neueste MongoDB einrichten, um die Unterstützung für neue native Transaktionen zu testen.

Um loszulegen, müssen wir die neueste Version vonMongoDB Download Center herunterladen.

Als Nächstes starten wir den Dienst vonmongodüber die Befehlszeile:

mongod --replSet rs0

Initiieren Sie abschließend den Replikatsatz - 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 unserenpom.xml die folgenden Abhängigkeiten hinzufügen:


    org.springframework.data
    spring-data-mongodb
    2.1.0.RELEASE



    org.springframework.data
    spring-data-releasetrain
    Lovelace-M3
    pom
    import

Beachten Sie, dass wir das Meilenstein-Repository auch zu unserenpom.xmlhinzufügen müssen:


    
        spring-milestones
        Spring Milestones
        https://repo.spring.io/milestone
        
            false
        
    

Die neueste Version der Bibliothek finden Sie aufCentral Repository

4. MongoDB-Konfiguration

Schauen wir uns nun unsere Konfiguration an:

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

Beachten Sie, dasswe need to register MongoTransactionManagerin unserer Konfiguration enthalten ist, um native MongoDB-Transaktionen zu aktivieren, da diese standardmäßig deaktiviert sind.

5. Synchrone Transaktionen

Nachdem wir die Konfiguration abgeschlossen haben, müssen wir nur nochannotate our method with*@Transactional*. verwenden, um native MongoDB-Transaktionen zu verwenden

Alles innerhalb der mit Annotationen versehenen 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 users = mongoTemplate.find(query, User.class);

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

Beachten Sie, dass wir den BefehllistCollectionsnicht in einer Transaktion mit mehreren Dokumenten verwenden können - 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));
    }
}

In diesem Beispiel wirdMongoTransactionException ausgelöst, da wir die MethodecollectionExists() verwendet haben.

Wir könnencount auch nicht in einer Transaktion mit mehreren Dokumenten ausführen:

@Test(expected = MongoCommandException.class)
@Transactional
public void whenCountDuringMongoTransaction_thenException() {
    userRepository.save(new User("John", 30));
    userRepository.save(new User("Ringo", 35));
    userRepository.count();
}

Wir können dieses Problem jedoch mit einer einfachen Abfrage umgehen und dann die Größe der resultierenden Liste ermitteln:

@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

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

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

Wir müssenSessionSynchronization aufALWAYS setzen, um nicht native Spring Data-Transaktionen zu verwenden.

7. Reaktive Transaktionen

Zum Schluss schauen wir unsSpring Data support for MongoDB reactive transactions an.

Wir müssen denpom.xml einige weitere Abhängigkeiten hinzufügen, um mit reaktiver MongoDB arbeiten zu können:


    org.mongodb
    mongodb-driver-reactivestreams
    1.9.2



    io.projectreactor
    reactor-test
    3.2.0.RELEASE
    test

Die Abhängigkeitenmongodb-driver-reactivestreams undreactor-test sind in Maven Central verfügbar.

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

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

Um Transaktionen in reaktiven MongoDB zu verwenden, müssen wir dieinTransaction()-Methode inReactiveMongoOperations verwenden:

@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 unterhere.

8. Fazit

In diesem Artikel haben wir gelernt, wie man native und nicht native MongoDB-Transaktionen mit Spring Data verwendet.

Der vollständige Quellcode für die Beispiele istover on GitHub. verfügbar