1. Přehled
Počínaje verzí 4.0 podporuje MongoDB transakce ACID s více dokumenty. A Spring Data Lovelace nyní poskytuje podporu pro tyto nativní transakce MongoDB .
V tomto tutoriálu probereme podporu Spring Data MongoDB pro synchronní a reaktivní transakce.
Podíváme se také na Spring Data TransactionTemplate pro podporu jiných než nativních transakcí.
Pro úvod k tomuto modulu Spring Data se podívejte na náš úvodní zápis.
2. Nastavení MongoDB 4.0
Nejprve budeme muset nastavit nejnovější MongoDB, abychom vyzkoušeli novou podporu nativních transakcí.
Abychom mohli začít, musíme si stáhnout nejnovější verzi z MongoDB Download Center.
Dále začneme mongod pomocí příkazového řádku:
mongod --replSet rs0
Nakonec spusťte sadu replik – pokud již ne:
mongo --eval "rs.initiate()"
Všimněte si, že MongoDB aktuálně podporuje transakce přes sadu replik.
3. Maven Configuration
Dále musíme do pom.xml přidat následující závislosti :
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
Nejnovější verzi knihovny lze nalézt na Centrálním úložišti
4. Konfigurace MongoDB
Nyní se podívejme na naši konfiguraci:
@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);
}
}
Upozorňujeme, že musíme zaregistrovat MongoTransactionManager v naší konfiguraci povolit nativní transakce MongoDB, protože jsou ve výchozím nastavení zakázány.
5. Synchronní transakce
Po dokončení konfigurace vše, co musíme udělat, abychom mohli používat nativní transakce MongoDB – je anotovat naši metodu pomocí @Transakční .
Vše v anotované metodě bude provedeno v jedné transakci:
@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));
}
Upozorňujeme, že nemůžeme použít listCollections příkaz uvnitř transakce s více dokumenty – například:
@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));
}
}
Tento příklad vyvolá výjimku MongoTransactionException jak jsme použili collectionExists() metoda.
6. TransactionTemplate
Viděli jsme, jak Spring Data podporují novou nativní transakci MongoDB. Kromě toho nabízí Spring Data také nenativní možnost.
Nenativní transakce můžeme provádět pomocí 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));
}
Musíme nastavit SessionSynchronization až VŽDY používat jiné než nativní transakce Spring Data.
7. Reaktivní transakce
Nakonec se podíváme na podporu jarních dat pro reaktivní transakce MongoDB .
Do pom.xml budeme muset přidat několik dalších závislostí pro práci s reaktivním MongoDB:
<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>
Závislosti mongodb-driver-reactivestreams, mongodb-driver-sync a reaktor-test jsou dostupné na Maven Central.
A samozřejmě musíme nakonfigurovat náš Reactive MongoDB:
@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";
}
}
Abychom mohli používat transakce v reaktivním MongoDB, musíme použít inTransaction() metoda v 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)));
}
Více informací o reaktivních úložištích ve Spring Data je k dispozici zde.