Automatisch generiertes Feld für MongoDB mit Spring Boot

Automatisch generiertes Feld für MongoDB mit Spring Boot

1. Überblick

In diesem Tutorial erfahren Sie, wie Sie ein sequentielles, automatisch generiertes Feld für MongoDB in Spring Boot implementieren.

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. Daher benötigen wir eine Methode, um den gleichen Effekt zu erzielen, den wir haben, wenn wir JPA und eine SQL-Datenbank verwenden.

Die allgemeine Lösung für dieses Problem ist einfach. Wir erstellen eine Sammlung (Tabelle), in der die generierte Sequenz für andere Sammlungen gespeichert wird. Während der Erstellung eines neuen Datensatzes wird dieser verwendet, um den nächsten Wert abzurufen.

2. Abhängigkeiten

Fügen wir unserenpom.xml die folgenden Spring-Boot-Starter hinzu:


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

Die neueste Version für die Abhängigkeiten wird vonspring-boot-starter-parent verwaltet.

3. Sammlungen

Wie in der Übersicht erläutert, erstellen wir eine Sammlung, in der die automatisch inkrementierte Sequenz für andere Sammlungen gespeichert wird. Wir werden diese Sammlungdatabase_sequences. nennen. Sie kann entweder mit dermongo-Shell oder mit MongoDB Compass erstellt werden. Erstellen wir eine entsprechende Modellklasse:

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

    @Id
    private String id;

    private long seq;

    //getters and setters omitted
}

Erstellen wir dann eineusers-Sammlung und ein entsprechendes Modellobjekt, in dem die Details der Personen gespeichert werden, die unser System verwenden:

@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 dem oben erstelltenUser-Modell haben wir ein statisches FeldSEQUENCE_NAME, hinzugefügt, das eine eindeutige Referenz auf die automatisch inkrementierte Sequenz für dieusers-Sammlung darstellt.

Wir kommentieren es auch mit@Transient, um zu verhindern, dass es neben anderen Eigenschaften des Modells beibehalten wird.

4. Neuen Datensatz erstellen

Bisher haben wir die erforderlichen Kollektionen und Modelle erstellt. Jetzt erstellen wir einen Service, der den automatisch inkrementierten Wert generiert, der alsidfür unsere Entitäten verwendet werden kann.

Erstellen wir einSequenceGeneratorService mitgenerateSequence():

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

Jetzt können wir diegenerateSequence() verwenden, während wir einen neuen Datensatz erstellen:

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

Um alle Benutzer aufzulisten, verwenden wirUserRepository:

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

So wie es jetzt ist, müssen wir das ID-Feld jedes Mal festlegen, wenn wir eine neue Instanz unseres Modells erstellen. Wir können diesen Prozess umgehen, indem wir einen Listener für Spring Data MongoDB-Lebenszyklusereignisse erstellen.

Dazu erstellen wir einUserModelListener, dasAbstractMongoEventListener<User> erweitert, und überschreiben dann dasonBeforeConvert():

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

Jedes Mal, wenn wir ein neuesUser, speichern, werden dieid automatisch gesetzt.

5. Fazit

Zusammenfassend haben wir gesehen, wie sequentielle, automatisch inkrementierte Werte für das ID-Feld generiert und dasselbe Verhalten wie in SQL-Datenbanken simuliert werden.

Der Ruhezustand verwendet standardmäßig eine ähnliche Methode zum Generieren von automatisch inkrementierten Werten.

Wie üblich ist der vollständige Quellcodeover on Github verfügbar.