Einführung in Spring Data MongoDB

Einführung in Spring Data MongoDB

1. Überblick

Dieser Artikel wird eine schnelle und praktischeintroduction to Spring Data MongoDB sein.

Wir werden die Grundlagen anhand vonMongoTemplate undMongoRepository anhand praktischer Beispiele erläutern, um jede Operation zu veranschaulichen.

Weitere Lektüre:

Geospatial Support in MongoDB

Erfahren Sie, wie Sie mit MongoDB Geodaten speichern, indizieren und durchsuchen

Read more

Spring Boot Integrationstest mit Embedded MongoDB

Erfahren Sie, wie Sie die eingebettete MongoDB-Lösung von Flapdoodle zusammen mit Spring Boot verwenden, um MongoDB-Integrationstests reibungslos auszuführen.

Read more

2. MongoTemplateand MongoRepository

The MongoTemplate folgt im Frühjahr dem Standardvorlagenmuster und bietet eine sofort einsatzbereite Basis-API für die zugrunde liegende Persistenz-Engine.

The repository folgt dem Spring Data-zentrierten Ansatz und bietet flexiblere und komplexere API-Operationen, die auf den bekannten Zugriffsmustern in allen Spring Data-Projekten basieren.

Für beide müssen wir zunächst die Abhängigkeit definieren - zum Beispiel inpom.xml mit Maven:


    org.springframework.data
    spring-data-mongodb
    2.1.9.RELEASE



    org.springframework.data
    spring-data-releasetrain
    Lovelace-SR9
    pom
    import

Um zu überprüfen, ob eine neue Version der Bibliothek veröffentlicht wurde -track the releases here.

3. Konfiguration fürMongoTemplate

3.1. XML-Konfiguration

Beginnen wir mit der einfachen XML-Konfiguration für die Mongo-Vorlage:


Zuerst müssen wir die Factory-Bean definieren, die für die Erstellung von Mongo-Instanzen verantwortlich ist.

Als nächstes müssen wir die Template Bean definieren (und konfigurieren):


    

Und schließlich müssen wir einen Postprozessor definieren, um alleMongoExceptionszu übersetzen, die in die mit@Repositorykommentierten Klassen geworfen werden:

3.2. Java-Konfiguration

Erstellen wir jetzt eine ähnliche Konfiguration mit der Java-Konfiguration, indem wir die Basisklasse für die MongoDB-KonfigurationAbstractMongoConfiguration erweitern:

@Configuration
public class MongoConfig extends AbstractMongoConfiguration {

    @Override
    protected String getDatabaseName() {
        return "test";
    }

    @Override
    public MongoClient mongoClient() {
        return new MongoClient("127.0.0.1", 27017);
    }

    @Override
    protected String getMappingBasePackage() {
        return "org.example";
    }
}

Hinweis: In der vorherigen Konfiguration mussten wirMongoTemplate Bean nicht definieren, da sie bereits inAbstractMongoConfiguration definiert ist

Wir können unsere Konfiguration auch von Grund auf neu verwenden, ohneAbstractMongoConfiguration zu verlängern - wie folgt:

@Configuration
public class SimpleMongoConfig {

    @Bean
    public MongoClient mongo() {
        return new MongoClient("localhost");
    }

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {
        return new MongoTemplate(mongo(), "test");
    }
}

4. Konfiguration fürMongoRepository

4.1. XML-Konfiguration

Um benutzerdefinierte Repositorys zu verwenden (MongoRepository erweitern), müssen Sie die Konfiguration ab Abschnitt 3.1 fortsetzen und die Repositorys einrichten:

4.2. Java-Konfiguration

In ähnlicher Weise bauen wir auf der Konfiguration auf, die wir bereits in Abschnitt 3.2 erstellt haben, und fügen dem Mix eine neue Anmerkung hinzu:

@EnableMongoRepositories(basePackages = "org.example.repository")

4.3. Erstellen Sie das Repository

Nach der Konfiguration müssen wir nun ein Repository erstellen, das die vorhandeneMongoRepository-Schnittstelle erweitert:

public interface UserRepository extends MongoRepository {
    //
}

Jetzt können wir dieseUserRepository automatisch verkabeln und Operationen vonMongoRepository verwenden oder benutzerdefinierte Operationen hinzufügen.

5. Verwenden vonMongoTemplate

5.1. Insert

Beginnen wir mit dem Einfügevorgang. Beginnen wir auch mit einer leeren Datenbank:

{
}

Wenn wir jetzt einen neuen Benutzer einfügen:

User user = new User();
user.setName("Jon");
mongoTemplate.insert(user, "user");

Die Datenbank sieht folgendermaßen aus:

{
    "_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
    "_class" : "org.example.model.User",
    "name" : "Jon"
}

5.2. Save – Insert

Die Operationsavehat eine Semantik zum Speichern oder Aktualisieren: Wenn eine ID vorhanden ist, führt sie eine Aktualisierung durch, wenn nicht, führt sie eine Einfügung durch.

Schauen wir uns die erste Semantik an - die Einfügung; Hier ist der Anfangszustand der Datenbank:

{
}

Wenn wir jetztsaveein neuer Benutzer sind:

User user = new User();
user.setName("Albert");
mongoTemplate.save(user, "user");

Die Entität wird in die Datenbank eingefügt:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Albert"
}

Als Nächstes betrachten wir dieselbe Operation -save - mit Aktualisierungssemantik.

5.3. Save – Update

Betrachten wir nunsave mit Aktualisierungssemantik, die auf einer vorhandenen Entität ausgeführt werden:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Jack"
}

Wenn wirsaveder vorhandene Benutzer sind, werden wir ihn aktualisieren:

user = mongoTemplate.findOne(
  Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
mongoTemplate.save(user, "user");

Die Datenbank sieht folgendermaßen aus:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Jim"
}

Wie Sie sehen können, verwendetsave in diesem Beispiel die Semantik vonupdate, da wir ein Objekt mit bestimmten_id verwenden.

5.4. UpdateFirst

updateFirst aktualisiert das allererste Dokument, das der Abfrage entspricht.

Beginnen wir mit dem Anfangszustand der Datenbank:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Alex"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.example.model.User",
        "name" : "Alex"
    }
]

Wenn wir jetzt dieupdateFirst ausführen:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Alex"));
Update update = new Update();
update.set("name", "James");
mongoTemplate.updateFirst(query, update, User.class);

Nur der erste Eintrag wird aktualisiert:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "James"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.example.model.User",
        "name" : "Alex"
    }
]

5.5. UpdateMulti

UpdateMultiupdates all document that matches the given query.

Erstens - hier ist der Status der Datenbank, bevor SieupdateMultiausführen:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Eugen"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.example.model.User",
        "name" : "Eugen"
    }
]

Lassen Sie uns nun die OperationupdateMultiausführen:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Eugen"));
Update update = new Update();
update.set("name", "Victor");
mongoTemplate.updateMulti(query, update, User.class);

Beide vorhandenen Objekte werden in der Datenbank aktualisiert:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Victor"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.example.model.User",
        "name" : "Victor"
    }
]

5.6. FindAndModify

Diese Operation funktioniert wieupdateMulti, aberreturns the object before it was modified.

Erstens - den Status der Datenbank vor dem Aufruf vonfindAndModify:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Markus"
}

Schauen wir uns den tatsächlichen Operationscode an:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Markus"));
Update update = new Update();
update.set("name", "Nick");
User user = mongoTemplate.findAndModify(query, update, User.class);

Das zurückgegebeneuser object hat dieselben Werte wie der Anfangszustand in der Datenbank.

Der neue Status in der Datenbank lautet jedoch:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Nick"
}

5.7. Upsert

Dieupsert arbeiten mit denfind and modify else create semantics: Wenn das Dokument übereinstimmt, aktualisieren Sie es, andernfalls erstellen Sie ein neues Dokument, indem Sie die Abfrage und das Aktualisierungsobjekt kombinieren.

Beginnen wir mit dem Anfangszustand der Datenbank:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Markus"
}

Führen Sie nun dieupsert aus:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Markus"));
Update update = new Update();
update.set("name", "Nick");
mongoTemplate.upsert(query, update, User.class);

Hier ist der Status der Datenbank nach dem Vorgang:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Nick"
}

5.8. Remove

Der Status der Datenbank vor dem Aufruf vonremove:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Benn"
}

Lassen Sie uns jetztremove ausführen:

mongoTemplate.remove(user, "user");

Das Ergebnis wird erwartet:

{
}

6. Verwenden vonMongoRepository

6.1. Insert

Erstens - den Status der Datenbank vor dem Ausführen voninsert:

{
}

Wenn wir jetzt einen neuen Benutzer einfügen:

User user = new User();
user.setName("Jon");
userRepository.insert(user);

Hier ist der Endzustand der Datenbank:

{
    "_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
    "_class" : "org.example.model.User",
    "name" : "Jon"
}

Beachten Sie, wie die Operation genauso funktioniert wie dieinsert in derMongoTemplate-API.

6.2. Save -Insert

In ähnlicher Weise funktioniert -save genauso wie die Operationsave in derMongoTemplate-API.

Betrachten wir zunächstthe insert semantics der Operation. Hier ist der Anfangszustand der Datenbank:

{
}

Jetzt führen wir die Operationsaveaus:

User user = new User();
user.setName("Aaron");
userRepository.save(user);

Dies führt dazu, dass der Benutzer der Datenbank hinzugefügt wird:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Aaron"
}

Beachten Sie noch einmal, wie in diesem Beispielsave mit der Semantik voninsertfunktioniert, da wir ein neues Objekt einfügen.

6.3. Save -Update

Betrachten wir nun dieselbe Operation, jedoch mitupdate semantics.

Erstens - hier ist der Status der Datenbank, bevor die neuensave:ausgeführt werden

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Jack"81*6
}

Nun führen wir die Operation aus:

user = mongoTemplate.findOne(
  Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
userRepository.save(user);

Hier ist der Status der Datenbank:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Jim"
}

Beachten Sie erneut, wie in diesem Beispielsave mit der Semantik vonupdatefunktioniert, da wir ein vorhandenes Objekt verwenden.

6.4. Delete

Der Status der Datenbank vor dem Aufruf vondelete:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Benn"
}

Lassen Sie unsdelete ausführen:

userRepository.delete(user);

Das Ergebnis wird einfach sein:

{
}

6.5. FindOne

Der Status der Datenbank, wennfindOne aufgerufen wird:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Chris"
}

Führen wir nun diefindOne aus:

userRepository.findOne(user.getId())

Das Ergebnis, das die vorhandenen Daten zurückgibt:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Chris"
}

6.6. Exists

Der Status der Datenbank vor dem Aufruf vonexists:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Harris"
}

Lassen Sie uns nunexists ausführen:

boolean isExists = userRepository.exists(user.getId());

Was natürlichtrue zurückgibt.

6.7. FindAll #with[.pl-en] Sort#

Der Status der Datenbank vor dem Aufruf vonfindAll:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Brendan"
    },
    {
       "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
       "_class" : "org.example.model.User",
       "name" : "Adam"
    }
]

Lassen Sie uns jetztfindAll mitSort ausführen:

List users = userRepository.findAll(new Sort(Sort.Direction.ASC, "name"));

Das Ergebnis istsorted by name in ascending order:

[
    {
        "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Adam"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Brendan"
    }
]

6.8. FindAll #with[.pl-en] Pageable #

Der Status der Datenbank vor dem Aufruf vonfindAll:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Brendan"
    },
    {
        "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Adam"
    }
]

Führen wir nunfindAll mit einer Paginierungsanforderung aus:

Pageable pageableRequest = PageRequest.of(0, 1);
Page page = userRepository.findAll(pageableRequest);
List users = pages.getContent();

Die resultierendeusers-Liste besteht nur aus einem Benutzer: __

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Brendan"
}

7. Anmerkungen

Lassen Sie uns abschließend auch die einfachen Anmerkungen durchgehen, mit denen Spring Data diese API-Vorgänge steuert.

@Id
private String id;

Die Annotation der Feldebene@Idkann jeden Typ schmücken, einschließlichlong undstring.

Wenn der Wert des Felds@Idnicht null ist, wird es unverändert in der Datenbank gespeichert. Andernfalls geht der Konverter davon aus, dass SieObjectId in der Datenbank speichern möchten (entwederObjectId, String oderBigInteger Arbeit).

Weiter -@Document:

@Document
public class User {
    //
}

Diese Annotation besteht einfach ausmarks a class as being a domain object, die in der Datenbank gespeichert werden müssen, und ermöglicht es uns, den Namen der zu verwendenden Sammlung auszuwählen.

8. Fazit

Dieser Artikel war eine schnelle, aber umfassende Einführung in die Verwendung von MongoDB mit Spring Data, sowohl über dieMongoTemplate-API als auch unter Verwendung vonMongoRepository.

Die Implementierung all dieser Beispiele und Codefragmentecan be foundover on Github - dies ist ein Maven-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.