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