How to use mongodb transactions in Spring Boot

9084


MongoDB introduced much-awaited transactions feature in their 4.0 release is called 'Multi-Document transactions'.

What is Transaction

In MongoDB, each and every operation or query may modify a single document or multiple documents, For example, updateOne() operation updates one document is atomic, if we try to modify multiple documents by using a single operation like updateMany() is not atomic because of multiple documents are modifying in the collection. If we want to make multiple write operations as atomic we need a transaction.

In MongoDB 4.0 Multi-Document transactions support available for atomic operation on multiple writes.

Properties of Transaction

  • When the transaction has committed all data operations on the transaction will commit automatically.
  • If any operation fails, the transaction will fail.
  • When the transaction has failed all data operations on the transaction will roll back automatically.
  • Until transaction committed no write operation data will be exposed to the outside world.

In Version 4.0, Multi-Document transactions supports transaction on replica sets.

In Version 4.2, Multi-Document transactions supports transaction on replica sets, sharded clusters .

Operation on Transaction

  • CRUD operation is allowed in a transaction.
  • Write to a capped collection is also allowed.
  • Write to system.* collections.
  • For cursors created outside of a transaction, we can not use it inside of a transaction.
  • For cursors created inside of a transaction, we can use in outside of a transaction also.

Spring MongoDB configuration

@Configuration
static class Config extends AbstractMongoConfiguration {

	@Bean
	MongoTransactionManager transactionManager(MongoDbFactory dbFactory) {
		return new MongoTransactionManager(dbFactory);
	}

	// ...
}

Spring Service

By adding @Transactional to the service method, it automatically enables transactions to the below method, if any error occurs it reverts all mongo write operations.

@Transactional
public void addUsers() {
    userRepository.save(new User("Alex"));
    roleRepository.save(new User("Admin"));    
}