1. Panoramica
In questo tutorial impareremo come implementare un campo sequenziale, generato automaticamente per MongoDB in Spring Boot.
Quando utilizziamo MongoDB come database per un'applicazione Spring Boot, non possiamo utilizzare @GeneratedValue annotazione nei nostri modelli in quanto non disponibile. Quindi abbiamo bisogno di un metodo per produrre lo stesso effetto che avremo se usiamo JPA e un database SQL.
La soluzione generale a questo problema è semplice. Creeremo una raccolta (tabella) che memorizzerà la sequenza generata per altre raccolte. Durante la creazione di un nuovo record, lo utilizzeremo per recuperare il valore successivo.
2. Dipendenze
Aggiungiamo i seguenti avviatori di avvio a molla al nostro pom.xml :
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<versionId>2.2.2.RELEASE</versionId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<versionId>2.2.2.RELEASE</versionId>
</dependency>
</dependencies>
L'ultima versione per le dipendenze è gestita da spring-boot-starter-parent .
3. Raccolte
Come discusso nella panoramica, creeremo una raccolta che memorizzerà la sequenza incrementata automaticamente per altre raccolte. Chiameremo questa raccolta database_sequences. Può essere creato utilizzando il mongo shell o MongoDB Compass. Creiamo una classe modello corrispondente:
@Document(collection = "database_sequences")
public class DatabaseSequence {
@Id
private String id;
private long seq;
//getters and setters omitted
}
Creiamo quindi un utenti raccolta e un oggetto modello corrispondente, che memorizzerà i dettagli delle persone che stanno utilizzando il nostro 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
}
In Utente modello creato sopra, abbiamo aggiunto un campo statico SEQUENCE_NAME, che è un riferimento univoco alla sequenza a incremento automatico per gli utenti raccolta.
Lo annotiamo anche con @Transient per evitare che venga mantenuto insieme ad altre proprietà del modello.
4. Creazione di un nuovo record
Finora abbiamo creato le collezioni e i modelli richiesti. Ora creeremo un servizio che genererà il valore incrementato automaticamente che può essere utilizzato come id per le nostre entità.
Creiamo un SequenceGeneratorService che ha generateSequence() :
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;
}
Ora possiamo utilizzare generateSequence() durante la creazione di un nuovo record:
User user = new User();
user.setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
user.setEmail("[email protected]");
userRepository.save(user);
Per elencare tutti gli utenti, utilizzeremo UserRepository :
List<User> storedUsers = userRepository.findAll();
storedUsers.forEach(System.out::println);
Come è ora, dobbiamo impostare il campo id ogni volta che creiamo una nuova istanza del nostro modello. Possiamo aggirare questo processo creando un listener per gli eventi del ciclo di vita di Spring Data MongoDB.
Per farlo, creeremo un UserModelListener che si estende AbstractMongoEventListener
@Override
public void onBeforeConvert(BeforeConvertEvent<User> event) {
if (event.getSource().getId() < 1) {
event.getSource().setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
}
}
Ora, ogni volta che salviamo un nuovo Utente l'id verrà impostato automaticamente.