Campo gerado automaticamente para o MongoDB usando o Spring Boot
1. Visão geral
Neste tutorial, vamos aprender como implementar um campo sequencial gerado automaticamente para MongoDB no Spring Boot.
When we’re using MongoDB as the database for a Spring Boot application, we can’t use @GeneratedValue annotation in our models as it’s not available. Portanto, precisamos de um método para produzir o mesmo efeito que teremos se estivermos usando JPA e um banco de dados SQL.
A solução geral para esse problema é simples. Vamos criar uma coleção (tabela) que armazenará a sequência gerada para outras coleções. Durante a criação de um novo registro, vamos usá-lo para buscar o próximo valor.
2. Dependências
Vamos adicionar os seguintes iniciadores de inicialização rápida ao nossopom.xml:
org.springframework.boot
spring-boot-starter-web
2.1.0.RELEASE
org.springframework.boot
spring-boot-starter-data-mongodb
2.1.0.RELEASE
A versão mais recente para as dependências é gerenciada porspring-boot-starter-parent.
3. Colecções
Conforme discutido na visão geral, criaremos uma coleção que armazenará a sequência incrementada automaticamente para outras coleções. Chamaremos essa coleção dedatabase_sequences. . Ela pode ser criada usando o shellmongo ou o MongoDB Compass. Vamos criar uma classe de modelo correspondente:
@Document(collection = "database_sequences")
public class DatabaseSequence {
@Id
private String id;
private long seq;
//getters and setters omitted
}
Vamos então criar uma coleçãousers e um objeto modelo correspondente, que armazenará os detalhes das pessoas que estão usando nosso sistema:
@Document(collection = "users")
public class User {
@Transient
public static final String SEQUENCE_NAME = "users_sequence";
@Id
private long id;
private String email;
//getters and setters omitted
}
No modeloUser criado acima, adicionamos um campo estáticoSEQUENCE_NAME, que é uma referência única para a sequência autoincrementada para a coleçãousers.
Também anotamos com@Transient para evitar que seja persistido ao lado de outras propriedades do modelo.
4. Criação de um novo registro
Até agora, criamos as coleções e modelos necessários. Agora, vamos criar um serviço que vai gerar o valor auto-incrementado que pode ser usado comoid para nossas entidades.
Vamos criar umSequenceGeneratorService que tenhagenerateSequence():
public long generateSequence(String seqName) {
DatabaseSequence counter = mongoOperations.findAndModify(query(where("_id").is(seqName)),
new Update().inc("seq",1), options().returnNew(true).upsert(true),
DatabaseSequence.class);
return !Objects.isNull(counter) ? counter.getSeq() : 1;
}
Agora, podemos usargenerateSequence() ao criar um novo registro:
User user = new User();
user.setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
user.setEmail("[email protected]");
userRepository.save(user);
Para listar todos os usuários, usaremos oUserRepository:
List storedUsers = userRepository.findAll();
storedUsers.forEach(System.out::println);
Como está agora, temos que definir o campo id toda vez que criamos uma nova instância de nosso modelo. Podemos contornar esse processo criando um ouvinte para eventos de ciclo de vida do Spring Data MongoDB.
Para fazer isso, criaremos umUserModelListener que estendeAbstractMongoEventListener<User>e substituiremos oonBeforeConvert():
@Override
public void onBeforeConvert(BeforeConvertEvent event) {
if (event.getSource().getId() < 1) {
event.getSource().setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
}
}
Agora, toda vez que salvarmos um novoUser,, oid será definido automaticamente.
5. Conclusão
Em conclusão, vimos como gerar valores sequenciais, auto-incrementados para o campo id e simular o mesmo comportamento visto em bancos de dados SQL.
O Hibernate usa um método semelhante para gerar valores incrementados automaticamente por padrão.
Como de costume, o código-fonte completo está disponívelover on Github.