Champ généré automatiquement pour MongoDB à l’aide de Spring Boot

Champ généré automatiquement pour MongoDB à l'aide de Spring Boot

1. Vue d'ensemble

Dans ce didacticiel, nous allons apprendre à implémenter un champ séquentiel généré automatiquement pour MongoDB dans 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. Par conséquent, nous avons besoin d’une méthode pour produire le même effet que si nous utilisons JPA et une base de données SQL.

La solution générale à ce problème est simple. Nous allons créer une collection (table) qui stockera la séquence générée pour d'autres collections. Lors de la création d'un nouvel enregistrement, nous l'utiliserons pour récupérer la valeur suivante.

2. Les dépendances

Ajoutons les démarreurs Spring-Boot suivants à nospom.xml:


    
        org.springframework.boot
        spring-boot-starter-web
        2.1.0.RELEASE
    
    
        org.springframework.boot
        spring-boot-starter-data-mongodb
        2.1.0.RELEASE
    

La dernière version des dépendances est gérée parspring-boot-starter-parent.

3. Des collections

Comme indiqué dans la présentation, nous allons créer une collection qui stockera la séquence auto-incrémentée pour d'autres collections. Nous appellerons cette collectiondatabase_sequences. . Elle peut être créée à l'aide du shellmongo ou de MongoDB Compass. Créons une classe de modèle correspondante:

@Document(collection = "database_sequences")
public class DatabaseSequence {

    @Id
    private String id;

    private long seq;

    //getters and setters omitted
}

Créons ensuite une collectionusers et un objet modèle correspondant, qui stockeront les détails des personnes qui utilisent notre système:

@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
}

Dans le modèleUser créé ci-dessus, nous avons ajouté un champ statiqueSEQUENCE_NAME, qui est une référence unique à la séquence auto-incrémentée pour la collectionusers.

Nous l'annotons également avec les@Transient pour éviter qu'il ne soit conservé aux côtés d'autres propriétés du modèle.

4. Créer un nouvel enregistrement

Jusqu'à présent, nous avons créé les collections et les modèles requis. Maintenant, nous allons créer un service qui générera la valeur auto-incrémentée qui peut être utilisée commeid pour nos entités.

Créons unSequenceGeneratorService qui agenerateSequence():

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;
}

Maintenant, nous pouvons utiliser lesgenerateSequence() lors de la création d'un nouvel enregistrement:

User user = new User();
user.setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
user.setEmail("[email protected]");
userRepository.save(user);

Pour lister tous les utilisateurs, nous utiliserons lesUserRepository:

List storedUsers = userRepository.findAll();
storedUsers.forEach(System.out::println);

Dans l'état actuel des choses, nous devons définir le champ id à chaque fois que nous créons une nouvelle instance de notre modèle. Nous pouvons contourner ce processus en créant un écouteur pour les événements du cycle de vie Spring Data MongoDB.

Pour ce faire, nous allons créer unUserModelListener qui étendAbstractMongoEventListener<User>, puis nous remplacerons lesonBeforeConvert():

@Override
public void onBeforeConvert(BeforeConvertEvent event) {
    if (event.getSource().getId() < 1) {
        event.getSource().setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
    }
}

Désormais, chaque fois que nous sauvegardons un nouveauUser,, leid sera défini automatiquement.

5. Conclusion

En conclusion, nous avons vu comment générer des valeurs séquentielles auto-incrémentées pour le champ id et simuler le même comportement que celui observé dans les bases de données SQL.

Hibernate utilise une méthode similaire pour générer par défaut des valeurs auto-incrémentées.

Comme d'habitude, le code source complet est disponibleover on Github.