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