Transações do Spring Data MongoDB
1. Visão geral
A partir da versão 4.0, o MongoDB suporta transações ACID para vários documentos. E,Spring Data Lovelace now provides support for these native MongoDB transactions.
Neste tutorial, discutiremos o suporte do Spring Data MongoDB para transações síncronas e reativas.
Também daremos uma olhada no Spring DataTransactionTemplate para suporte a transações não nativas.
Para uma introdução a este módulo Spring Data, dê uma olhada em nossointroductory write-up.
2. Configurar MongoDB 4.0
Primeiro, precisaremos configurar o MongoDB mais recente para experimentar o novo suporte a transações nativas.
Para começar, temos que baixar a versão mais recente deMongoDB Download Center.
A seguir, iniciaremos o serviçomongod usando a linha de comando:
mongod --replSet rs0
Por fim, inicie o conjunto de réplicas - se ainda não estiver:
mongo --eval "rs.initiate()"
Observe que o MongoDB atualmente suporta transações em um conjunto de réplicas.
3. Configuração do Maven
Em seguida, precisamos adicionar as seguintes dependências ao nossopom.xml:
org.springframework.data
spring-data-mongodb
2.1.0.RELEASE
org.springframework.data
spring-data-releasetrain
Lovelace-M3
pom
import
Observe que precisamos adicionar o repositório de marcos ao nossopom.xml também:
spring-milestones
Spring Milestones
https://repo.spring.io/milestone
false
A versão mais recente da biblioteca pode ser encontrada emCentral Repository
4. Configuração do MongoDB
Agora, vamos dar uma olhada em nossa configuração:
@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);
}
}
Observe quewe need to register MongoTransactionManager em nossa configuração para habilitar transações nativas do MongoDB, pois elas são desabilitadas por padrão.
5. Transações síncronas
Depois de terminar a configuração, tudo o que precisamos fazer para usar as transações nativas do MongoDB - éannotate our method with*@Transactional*.
Tudo dentro do método anotado será executado em uma transação:
@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));
}
Observe que não podemos usar o comandolistCollections dentro de uma transação de vários documentos - por exemplo:
@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));
}
}
Este exemplo lança umMongoTransactionException, pois usamos o métodocollectionExists().
Também não podemos executarcount dentro de uma transação de vários documentos:
@Test(expected = MongoCommandException.class)
@Transactional
public void whenCountDuringMongoTransaction_thenException() {
userRepository.save(new User("John", 30));
userRepository.save(new User("Ringo", 35));
userRepository.count();
}
Porém, podemos solucionar esse problema com uma consulta simples e obter o tamanho da lista resultante:
@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
Vimos como o Spring Data suporta novas transações nativas do MongoDB. Além disso, o Spring Data também fornece a opção não nativa.
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));
}
Precisamos definirSessionSynchronization paraALWAYS para usar transações não nativas do Spring Data.
7. Transações Reativas
Finalmente, daremos uma olhada emSpring Data support for MongoDB reactive transactions.
Precisaremos adicionar mais algumas dependências apom.xml para trabalhar com MongoDB reativo:
org.mongodb
mongodb-driver-reactivestreams
1.9.2
io.projectreactor
reactor-test
3.2.0.RELEASE
test
As dependênciasmongodb-driver-reactivestreamsereactor-test estão disponíveis no Maven Central.
E, é claro, precisamos configurar nosso MongoDB reativo:
@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";
}
}
Para usar transações no MongoDB reativo, precisamos usar o métodoinTransaction() emReactiveMongoOperations:
@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)));
}
Mais informações sobre repositórios reativos no Spring Data estão disponíveishere.
8. Conclusão
Neste artigo, aprendemos como usar transações MongoDB nativas e não nativas usando o Spring Data.
O código-fonte completo dos exemplos está disponívelover on GitHub.