Background
Unlike Spring Data JPA, Spring Data MongoDB does not support @Transactional
out of the box. In this guide, we will explore how to implement @Transactional
with Spring Data MongoDB.
Scenario
We will implement based on the following scenario:
When a new User is created
Then the status should be ACTIVE
Implementation
Integration Test
We will verify our implementation through integration test whereby we will create a new User
and verify that the status is ACTIVE
.
@SpringBootTest(webEnvironment = RANDOM_PORT)
@Testcontainers
class CreateUserTests {
@Container
@ServiceConnection
private static final MongoDBContainer mongo = new MongoDBContainer("mongo:latest");
@Autowired
private TestRestTemplate restTemplate;
@Test
void create() {
var headers = new HttpHeaders() {{ setContentType(APPLICATION_JSON); }};
var body = """
{
"username": "rashidi.zin",
"name": "Rashidi Zin"
}
""";
var response = restTemplate.exchange("/users", POST, new HttpEntity<>(body, headers), User.class);
var createdUser = response.getBody();
assertThat(createdUser).extracting("status").isEqualTo(ACTIVE);
}
}
Event Listener
We will start by implementing an EventListener
that will be responsible to assign the status to ACTIVE
when a new User
is created.
@Component
class UpdateUserStatus {
@TransactionalEventListener
public void onBeforeSave(BeforeSaveEvent<User> event) {
var user = event.getSource();
user.status(ACTIVE);
}
}
As we can see, onBeforeSave
is annotated with @TransactionalEventListener
. This annotation will ensure that the event listener will be
executed within a transaction.
Transactional Method
Next, we will implement a transactional method that will create a new User
.
@RestController
class UserResource {
private final UserRepository repository;
UserResource(UserRepository repository) {
this.repository = repository;
}
@PostMapping("/users")
@ResponseStatus(CREATED)
@Transactional
public User add(@RequestBody User user) {
return repository.save(user);
}
}
Configuration Class
Finally, we will configure MongoTransactionManager
to enable transaction support for MongoDB.
@Configuration
@EnableTransactionManagement
class MongoTransactionManagerConfiguration {
@Bean
public PlatformTransactionManager transactionManager(MongoDatabaseFactory factory) {
return new MongoTransactionManager(factory);
}
}
Verification
In order to ensure that our implementation is working as expected, the test implemented in CreateUserTests should pass.