MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

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

1. Présentation

Dans ce didacticiel, nous allons apprendre à implémenter un champ séquentiel généré automatiquement pour MongoDB dans Spring Boot.

Lorsque nous utilisons MongoDB comme base de données pour une application Spring Boot, nous ne pouvons pas utiliser @GeneratedValue annotation dans nos modèles car elle n'est pas disponible. Nous avons donc besoin d'une méthode pour produire le même effet que si nous utilisions 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. Dépendances

Ajoutons les démarreurs de démarrage de printemps suivants à notre 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>

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

3. 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 collection database_sequences. Il peut être créé en utilisant soit le mongo shell ou boussole MongoDB. 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 un utilisateurs collection, et un objet modèle correspondant, qui stockera 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 Utilisateur modèle créé ci-dessus, nous avons ajouté un champ statique SEQUENCE_NAME, qui est une référence unique à la séquence auto-incrémentée pour les utilisateurs collecte.

Nous l'annotons également avec @Transient pour l'empêcher d'être conservé avec 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. Nous allons maintenant créer un service qui générera la valeur auto-incrémentée pouvant être utilisée comme id pour nos entités.

Créons un SequenceGeneratorService qui a 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;
}

Maintenant, nous pouvons utiliser generateSequence() 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 répertorier tous les utilisateurs, nous utiliserons le UserRepository :

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

Comme c'est le cas maintenant, 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 un UserModelListener qui étend AbstractMongoEventListener puis nous remplacerons le onBeforeConvert() :

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

Désormais, chaque fois que nous enregistrons un nouvel utilisateur, l'identifiant sera défini automatiquement.