MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Automatisch generiertes Feld für MongoDB mit Spring Boot

1. Übersicht

In diesem Tutorial lernen wir, wie man ein sequentielles, automatisch generiertes Feld für MongoDB in Spring Boot implementiert.

Wenn wir MongoDB als Datenbank für eine Spring Boot-Anwendung verwenden, können wir @GeneratedValue nicht verwenden Anmerkung in unseren Modellen, da sie nicht verfügbar ist. Daher brauchen 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), die die generierte Sequenz für andere Sammlungen speichert. Während der Erstellung eines neuen Datensatzes verwenden wir ihn, um den nächsten Wert abzurufen.

2. Abhängigkeiten

Lassen Sie uns die folgenden Spring-Boot-Starter zu unserer pom.xml hinzufügen :

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

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

3. Sammlungen

Wie in der Übersicht besprochen, erstellen wir eine Sammlung, die die automatisch inkrementierte Sequenz für andere Sammlungen speichert. Wir nennen diese Sammlung database_sequences. Es kann entweder mit mongo erstellt werden Shell oder MongoDB Compass. Lassen Sie uns eine entsprechende Modellklasse erstellen:

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

    @Id
    private String id;

    private long seq;

    //getters and setters omitted
}

Lassen Sie uns dann einen Nutzer erstellen -Sammlung und ein entsprechendes Modellobjekt, das die Details von Personen speichert, 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
}

Im Benutzer oben erstellten Modell haben wir ein statisches Feld SEQUENCE_NAME, hinzugefügt Dies ist ein eindeutiger Verweis auf die automatisch inkrementierte Sequenz für die Nutzer Sammlung.

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

4. Erstellen eines neuen Datensatzes

Bisher haben wir die erforderlichen Kollektionen und Modelle erstellt. Jetzt erstellen wir einen Dienst, der den automatisch inkrementierten Wert generiert, der als id verwendet werden kann für unsere Unternehmen.

Lassen Sie uns einen SequenceGeneratorService erstellen das hat 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;
}

Jetzt können wir die generateSequence() verwenden beim Erstellen eines neuen Datensatzes:

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

Um alle Benutzer aufzulisten, verwenden wir das UserRepository :

List<User> 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 einen UserModelListener das erweitert AbstractMongoEventListener und dann überschreiben wir die onBeforeConvert() :

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

Jetzt speichern wir jedes Mal einen neuen Nutzer die ID wird automatisch gesetzt.