1. Overzicht
Vanaf release 4.0 ondersteunt MongoDB ACID-transacties met meerdere documenten. En Spring Data Lovelace biedt nu ondersteuning voor deze native MongoDB-transacties .
In deze zelfstudie bespreken we Spring Data MongoDB-ondersteuning voor synchrone en reactieve transacties.
We bekijken ook Spring Data TransactionTemplate voor ondersteuning van niet-native transacties.
Bekijk onze inleidende beschrijving voor een inleiding tot deze Spring Data-module.
2. MongoDB 4.0 instellen
Eerst moeten we de nieuwste MongoDB instellen om de nieuwe ondersteuning voor native transacties te proberen.
Om te beginnen, moeten we de nieuwste versie downloaden van het MongoDB Download Center.
Vervolgens beginnen we mongod service via de opdrachtregel:
mongod --replSet rs0
Start ten slotte de replicaset - als dat nog niet het geval is:
mongo --eval "rs.initiate()"
Merk op dat MongoDB momenteel transacties via een replicaset ondersteunt.
3. Maven-configuratie
Vervolgens moeten we de volgende afhankelijkheden toevoegen aan onze pom.xml :
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
De nieuwste release van de bibliotheek is te vinden op de Centrale Repository
4. MongoDB-configuratie
Laten we nu eens kijken naar onze configuratie:
@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);
}
}
Merk op dat we MongoTransactionManager moeten registreren in onze configuratie om native MongoDB-transacties in te schakelen omdat ze standaard zijn uitgeschakeld.
5. Synchrone transacties
Nadat we de configuratie hebben voltooid, hoeven we alleen maar native MongoDB-transacties te gebruiken:onze methode annoteren met @Transactional .
Alles binnen de geannoteerde methode wordt in één transactie uitgevoerd:
@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));
}
Houd er rekening mee dat we listCollections niet kunnen gebruiken commando binnen een transactie met meerdere documenten – bijvoorbeeld:
@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));
}
}
Dit voorbeeld genereert een MongoTransactionException zoals we de collectionExists() . gebruikten methode.
6. TransactionTemplate
We hebben gezien hoe Spring Data nieuwe native MongoDB-transacties ondersteunt. Daarnaast biedt Spring Data ook de niet-native optie.
We kunnen niet-native transacties uitvoeren met 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));
}
We moeten SessionSynchronization instellen naar ALTIJD om niet-eigen Spring Data-transacties te gebruiken.
7. Reactieve transacties
Ten slotte bekijken we Spring Data-ondersteuning voor MongoDB-reactieve transacties .
We moeten nog een paar afhankelijkheden toevoegen aan de pom.xml om te werken met reactieve 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>
De mongodb-driver-reactivestreams, mongodb-driver-sync en reactor-test-afhankelijkheden zijn beschikbaar op Maven Central.
En natuurlijk moeten we onze Reactive MongoDB configureren:
@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";
}
}
Om transacties in reactieve MongoDB te gebruiken, moeten we de inTransaction() . gebruiken 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)));
}
Meer informatie over reactieve opslagplaatsen in Spring Data is hier beschikbaar.