MongoDB ist eine NoSQL-Datenbank vom Typ Document Store.
Die hier gezeigten Einsteigerbeispiele zeigen, wie MongoDB per Kommandozeile, per Java und besonders komfortabel über Spring Data verwendet werden kann.
"NoSQL" steht für "not only SQL". Besser wäre vielleicht "not only relational". Anders als bei einer RDB (Relational database) bzw. einem RDBMS (Relational database management system) haben NoSQL-Datenbanken kein festes Datenbankschema mit festgelegten Typen und Tabellenstrukturen, arbeiten oft ohne Joins und ohne Relationen, und verwenden meistens keine referenzielle Integrität.
Laut dem CAP-Theorem ist es in einem verteilten System unmöglich, gleichzeitig die drei Eigenschaften Konsistenz (Consistency), Verfügbarkeit (Availability) und Partitionstoleranz (Partition tolerance) zu garantieren.
NoSQL-Datenbanken bieten meistens hohe Performance, hohe Ausfallsicherheit und besonders effektive horizontale Skalierung, oft durch Replikation und Sharding.
Einzelne NoSQL-Datenbanken können allerdings von den hier genannten allgemein üblichen Regeln abweichende Features bieten.
NoSQL-Datenbanken lassen sich grob in vier Kategorien einteilen:
Weitere Informationen finden Sie beispielsweise unter:
NoSQL, Wikipedia,
NoSQL-Übersicht, Eberhard Wolff,
NoSQL - die neue Datenbankgeneration, Eberhard Wolff.
MongoDB ist eine NoSQL-Datenbank vom Typ Document Store. MongoDB verwendet eigene Begriffe. Näherungsweise entsprechen einige in etwa den folgenden RDBMS-Begriffen:
RDBMS | MongoDB |
Table | Collection |
Row | Document |
Column | Field |
Primary Key | _id Field |
Index | Index |
Join | Embedded Document |
Foreign Key | Referenced Document |
Partition | Shard |
Auch bei den Datenzugriffen gibt es eigene Begriffe, die sich näherungsweise vergleichen lassen:
CRUD | IFUR |
Create | Insert |
Read | Find |
Update | Update |
Delete | Remove |
Weitere Informationen finden Sie beispielsweise unter:
MongoDB-Website,
MongoDB for Coder Training, Uwe Seiler.
Zur Installation von MongoDB unter anderen Betriebssystemen als Windows 10 64 Bit konsultieren Sie bitte das MongoDB Manual. Für Windows 10 64 Bit wählen Sie unter https://www.mongodb.org/downloads "Windows 64-bit 2008 R2+" und downloaden die Installationsdatei "mongodb-win32-x86_64-2008plus-ssl-3.2.0-signed.msi".
Sie können wahlweise
msiexec.exe /q /i mongodb-win32-x86_64-2008plus-ssl-3.2.0-signed.msi INSTALLLOCATION="D:\Tools\MongoDB" ADDLOCAL="all"
Überprüfen Sie die Installation (passen Sie den Pfad an):
dir D:\Tools\MongoDB\bin
Fügen Sie den MongoDB-bin-Pfad zu Ihrer PATH-Umgebungsvariable hinzu:
Betätigen Sie die Win-Taste+Pause-Taste, wählen Sie Erweiterte Systemeinstellungen | Umgebungsvariablen...
und fügen Sie über Benutzervariablen | PATH | Bearbeiten... am Ende des Wert-Textes hinzu (inkl. des vorangestellten Semikolons)
(passen Sie den Pfad an Ihre Installation an):
;D:\Tools\MongoDB\bin
Öffnen Sie ein neues Kommandozeilenfenster und testen Sie:
PATH
mongo --help
mongod --help
Diese einfache Installation genügt für die folgenden Beispiele. Konsultieren Sie das MongoDB Manual für weitere Installationsthemen, wie Authentifizierung, Replikation und Sharding.
Beim Start des MongoDB-Servers müssen Sie ein Verzeichnis für die Datenbasis angeben (so können Sie mit einer MongoDB-Installation mehrere Datenbasen verwenden) (passen Sie den gewünschten DB-Daten-Pfad "D:\Tools\MongoDB-Daten" an):
md D:\Tools\MongoDB-Daten
mongod -dbpath D:\Tools\MongoDB-Daten
Sie erhalten:
... I CONTROL [initandlisten] MongoDB starting : pid=7612 port=27017 dbpath=D:\Tools\MongoDB-Daten 64-bit host=MeinPC ... I CONTROL [initandlisten] db version v3.2.0 ... I NETWORK [initandlisten] waiting for connections on port 27017
Wie Sie MongoDB als automatisch startenden Windows-Dienst einrichten, erfahren Sie im MongoDB Manual im Kapitel "Configure a Windows Service for MongoDB".
Das im Windows-Kommandozeilenfenster eingegebene Kommando mongo öffnet die MongoDB-Konsole, in der die anschließend folgenden MongoDB-Kommandos eingegeben werden:
mongo
Legen Sie über die MongoDB-Konsole innerhalb der MongoDB eine neue Datenbank an:
help
show dbs
use meinmongotest
db
db.help()
db.createCollection( "personen1" )
show collections
Alternativ können Sie die Collection als "Capped Collection" definieren, etwa mit einer Maximalgröße,
bei deren Überschreitung die ältesten Elemente gelöscht werden:
db.createCollection( "meineCappedCollection", { capped: true, size: 100000, max: 100 } );
db.personen1.insert( { "vorname" : "Anton", "nachname" : "Alfa", "groesse" : 150 } )
db.personen1.insert( { "vorname" : "Berta", "nachname" : "Bravo", "groesse" : 190 } )
db.personen1.insert( { "vorname" : "Cäsar", "nachname" : "Charlie", "groesse" : 170 } )
db.personen1.insert( { "vorname" : "Dora", "nachname" : "Delta", "groesse" : 180 } )
db.personen1.insert( { "vorname" : "Emil", "nachname" : "Echo", "groesse" : 140 } )
db.personen1.insert( { "vorname" : "Felix", "nachname" : "Foxtrot", "groesse" : 170 } )
db.personen1.insert( { "vorname" : "Gustav", "nachname" : "Golf", "haarfarbe" : "blond" } )
db.personen1.insert( { "vorname" : "Gustav", "nachname" : "Golf", "haarfarbe" : "lila" } )
db.personen1.find().pretty()
db.personen1.find()
Sie erhalten (mit anderen ObjectIds):
{ "_id" : ObjectId("5649e5f408e8a481730021e0"), "vorname" : "Anton", "nachname" : "Alfa", "groesse" : 150 } { "_id" : ObjectId("5649e5f408e8a481730021e1"), "vorname" : "Berta", "nachname" : "Bravo", "groesse" : 190 } { "_id" : ObjectId("5649e5f408e8a481730021e2"), "vorname" : "Cäsar", "nachname" : "Charlie", "groesse" : 170 } { "_id" : ObjectId("5649e5f408e8a481730021e3"), "vorname" : "Dora", "nachname" : "Delta", "groesse" : 180 } { "_id" : ObjectId("5649e5f408e8a481730021e4"), "vorname" : "Emil", "nachname" : "Echo", "groesse" : 140 } { "_id" : ObjectId("5649e5f408e8a481730021e5"), "vorname" : "Felix", "nachname" : "Foxtrot", "groesse" : 170 } { "_id" : ObjectId("5649e5f408e8a481730021e6"), "vorname" : "Gustav", "nachname" : "Golf", "haarfarbe" : "blond" } { "_id" : ObjectId("5649e5f408e8a481730021e7"), "vorname" : "Gustav", "nachname" : "Golf", "haarfarbe" : "lila" }
"Query By Example":
db.personen1.find( { "vorname": "Cäsar" } );
db.personen1.find( { "nachname": "Golf" } );
Vergleichsoperatoren (z.B.: $gt:, $gte:, $lt:, $lte:, $eq:, $in:, $in: mit /<Reg-Ex>/, ^ = Anfang, . = beliebiger Buchstabe, /i = ignore case):
db.personen1.find( { "groesse": { $gt: 175 } } );
db.personen1.find( { "nachname": { $in: [ /^.o/, /BRAVO/i ] } } );
Oder mit $or::
db.personen1.find( { $or: [ { "vorname": "Anton" }, { "nachname": "Golf" } ] } )
Und mit $and:
db.personen1.find( { $and: [ { "vorname": "Gustav" }, { "haarfarbe" : "lila" } ] } )
Sortieren (auf- und absteigend):
db.personen1.find().sort( { "groesse" : 1 } );
db.personen1.find().sort( { "groesse" : -1 } );
Paging:
db.personen1.find().skip( 3 ).limit( 2 )
Spaltenauswahl (restricted Fields):
db.personen1.find( {}, { "_id": 0, "vorname" : 1, "groesse" : 1 } );
db.personen1.find( { "groesse" : { $lt : 180 } }, { "_id": 0, "vorname" : 1, "groesse" : 1 } );
Count:
db.personen1.count( { "vorname" : "Gustav" } )
Distinct:
db.personen1.distinct( "vorname" )
Group:
db.personen1.group( { key: { "haarfarbe": true }, initial: { "anzahl": 0 }, reduce: function( document, prev ) { prev.anzahl += 1; } } );
db.personen1.group( { key: { "groesse": true }, cond: { "groesse": { $gt: 160 } }, initial: { "groessesumme": 0 }, reduce: function( document, prev ) { prev.groessesumme += document.groesse; } } );
Beispiel-Collection für Map/Reduce:
db.createCollection( "buecher" );
db.buecher.insert( { "titel" : "Java SE", "autor" : "Jasmin", "verlag" : "JV-Verlag", "preis" : 29 } );
db.buecher.insert( { "titel" : "Java EE", "autor" : "Jasmin", "verlag" : "JV-Verlag", "preis" : 39 } );
db.buecher.insert( { "titel" : "JSON", "autor" : "Jasmin", "verlag" : "SX-Verlag", "preis" : 19 } );
db.buecher.insert( { "titel" : "noSQL", "autor" : "Norbert", "verlag" : "SX-Verlag", "preis" : 42 } );
db.buecher.insert( { "titel" : "XML", "autor" : "Norbert", "verlag" : "SX-Verlag", "preis" : 39 } );
Kurzes Beispiel für Map/Reduce:
db.buecher.mapReduce(
function() { emit( this.autor, this.preis ); },
function( key, values ) { return Array.sum( values ) },
{ out: "preissumme_pro_autor" } ).find();
Etwas ausführlicheres Beispiel für Map/Reduce:
var map = function() { emit( this.autor, { preis: this.preis } ); };
var reduce = function( key, values ) { var sum = 0; values.forEach( function( doc ) { sum += doc.preis; } ); return { "preissumme": sum }; };
db.buecher.mapReduce( map, reduce, { out: "preissumme_pro_autor" } );
db.preissumme_pro_autor.find();
Sehen Sie sich zu Map/Reduce an: Map-Reduce Manual, Map-Reduce Examples, mapReduce()-Referenzdoku.
Index auf das Attribut nachname mit aufsteigender Sortierung:
db.personen1.createIndex( { "nachname": 1 } )
Kombinierter Index auf die Attribute nachname mit aufsteigender Sortierung und groesse mit absteigender Sortierung:
db.personen1.createIndex( { "nachname": 1, "groesse": -1 } )
Anzeige der Indizes:
db.personen1.getIndexes()
Kontrolle des Ausführungsplans ohne Index:
db.personen1.find().explain()
Kontrolle des Ausführungsplans mit Index:
db.personen1.find( { "nachname": "Test" } ).explain()
Achtung: So wird nur ein einziger Datensatz upgedatet, obwohl es "Gustav" zweimal gibt:
db.personen1.update( { "vorname": "Gustav" }, { $set: { "nachname" : "Golf-1" } } )
db.personen1.find()
Nur mit "multi: true" werden alle Datensätze upgedatet:
db.personen1.update( { "vorname": "Gustav" }, { $set: { "nachname" : "Golf-2" } }, { multi: true } )
db.personen1.find()
Atomically Find and Modify:
person = db.personen1.findAndModify( { query: { "nachname" : "Foxtrot" }, update: { $set: { "groesse" : 175 } } } );
db.personen1.find( { "nachname": "Foxtrot" } );
Optimistik Locking:
db.personen1.insert( { "vorname" : "Willi", "nachname" : "Walzer", "version": 1 } );
personVorher = db.personen1.findOne( { "nachname" : "Walzer" } );
versionVorher = personVorher.version;
db.personen1.update( { "_id": personVorher._id, "version": versionVorher }, { $set: { "vorname": "Wolfgang", "version": ++versionVorher } } );
db.personen1.find( { "nachname": "Walzer" } );
db.personen1.remove( { "nachname" : "Golf-2" } )
db.personen1.find()
db.personen1.remove( { "nachname" : { $in: [ "Foxtrot", "Walzer" ] } } )
db.personen1.find()
show collections
db.buecher.drop()
show collections
exit
Falls manuell gestartet:
per: Strg+C
Falls als Windows-Dienst gestartet:
net stop MongoDB
Falls als Datenpfad D:\Tools\MongoDB-Daten gewählt wurde:
rd /S D:\Tools\MongoDB-Daten
Wenn Sie beim Starten des MongoDB-Servers den Parameter --rest hinzufügen, können Sie Datenbankabfragen per REST ausführen (siehe hierzu: HTTP REST Interface):
mongod -dbpath D:\Tools\MongoDB-Daten --rest
Sehen Sie sich im Webbrowser (oder per curl) Status-Infos an:
http://127.0.0.1:28017/serverStatus?text=1
http://127.0.0.1:28017/hostInfo?text=1
http://127.0.0.1:28017/top?text=1
Sehen Sie sich Ihre Daten an:
http://127.0.0.1:28017/listDatabases?text=1
{ "databases" : [ { "name" : "local", "sizeOnDisk" : 73728, "empty" : false }, { "name" : "meinmongotest", "sizeOnDisk" : 245760, "empty" : false }, { "name" : "test", "sizeOnDisk" : 8192, "empty" : false } ], "totalSize" : 327680, "ok" : 1 }
http://127.0.0.1:28017/meinmongotest/personen1/
{ "offset" : 0, "rows": [ { "_id" : { "$oid" : "5674719afa4e01e3fc7a3fc7" }, "vorname" : "Anton", "nachname" : "Alfa", "groesse" : 150 } , { "_id" : { "$oid" : "5674719afa4e01e3fc7a3fc8" }, "vorname" : "Berta", "nachname" : "Bravo", "groesse" : 190 } , { "_id" : { "$oid" : "5674719afa4e01e3fc7a3fc9" }, "vorname" : "Cäsar", "nachname" : "Charlie", "groesse" : 170 } , { "_id" : { "$oid" : "5674719afa4e01e3fc7a3fca" }, "vorname" : "Dora", "nachname" : "Delta", "groesse" : 180 } , { "_id" : { "$oid" : "5674719afa4e01e3fc7a3fcb" }, "vorname" : "Emil", "nachname" : "Echo", "groesse" : 140 } ], "total_rows" : 5 , "query" : {} , "millis" : 0 }
http://127.0.0.1:28017/meinmongotest/personen1/?filter_vorname=Emil
{ "offset" : 0, "rows": [ { "_id" : { "$oid" : "5674719afa4e01e3fc7a3fcb" }, "vorname" : "Emil", "nachname" : "Echo", "groesse" : 140 } ], "total_rows" : 1 , "query" : { "vorname" : "Emil" } , "millis" : 0 }
Das folgende Beispiel zeigt, wie Sie mit Java über den mongo-java-driver einfache CRUD/IFUR-MongoDB-Operationen durchführen, und wie JSON-Strings zu MongoDB-Documents und umgekehrt konvertiert werden.
Maven muss installiert sein.
Wechseln Sie in Ihr Workspace-Verzeichnis (z.B. \MeinWorkspace) und führen Sie folgende Kommandos aus:
cd \MeinWorkspace
md MongoDbMitJava
cd MongoDbMitJava
md src\main\java\mongodbmitjava
md src\test\java\mongodbmitjava
tree /F
Erstellen Sie im MongoDbMitJava-Projektverzeichnis die Maven-Projektkonfigurationsdatei: pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>mongodbmitjava</groupId> <artifactId>MongoDbMitJava</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>${project.artifactId}</name> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> </project>
Sie können im Maven-Repo nachsehen, ob es mittlerweile eine neuere Treiberversion gibt.
Fügen Sie im src\main\java\mongodbmitjava-Verzeichnis eine Util-Klasse hinzu: MongoDbUtil.java
package mongodbmitjava; import java.util.*; import org.bson.Document; import com.mongodb.MongoClient; import com.mongodb.client.*; public class MongoDbUtil { public static void main( String[] args ) { zeigeMongoDbsCollsDocs( "localhost", 27017 ); } /** Auflistung der DBs, Collections und Documents in einer MongoDB */ public static void zeigeMongoDbsCollsDocs( String host, int port ) { try( MongoClient mongo = new MongoClient( host, port ) ) { MongoIterable<String> itDbNames = mongo.listDatabaseNames(); System.out.println( "Auflistung der DBs, Collections und Documents in der MongoDB " + host + ":" + port ); for( String dbName : itDbNames ) { System.out.println( "MongoDatabase: " + dbName ); MongoDatabase db = mongo.getDatabase( dbName ); MongoIterable<String> itCollectionNames = db.listCollectionNames(); List<String> collectionNames = itCollectionNames.into( new ArrayList<String>() ); System.out.println( " Collections: " + collectionNames ); for( String collectionName : collectionNames ) { if( !"local".equals( dbName ) && !"system.indexes".equals( collectionName ) ) { MongoCollection<Document> collection = db.getCollection( collectionName ); System.out.println( " Collection " + collectionName + ":" ); for( Document doc : collection.find() ) { System.out.println( " " + doc.toJson() ); } } } } } } }
Sehen Sie sich die API-Doku an zu den Klassen: MongoClient, MongoDatabase, MongoCollection, MongoIterable, FindIterable, Document.
Fügen Sie im src\test\java\mongodbmitjava-Testverzeichnis eine JUnit-Modultestklasse hinzu: MongoDbMitJavaTest.java
package mongodbmitjava; import static org.junit.Assert.assertEquals; import java.util.*; import org.bson.Document; import org.junit.Test; import com.mongodb.MongoClient; import com.mongodb.client.*; /** Konvertierungen zwischen JSON-Strings und MongoDB-Documents */ public class MongoDbMitJavaTest { static final String HOST = "localhost"; static final int PORT = 27017; static final String DB = "meinmongotest"; static final String COLL = "personen2"; @Test public void testMongoDbMitJava() { try( MongoClient mongo = new MongoClient( HOST, PORT ) ) { MongoDatabase db = mongo.getDatabase( DB ); MongoCollection<Document> collection = db.getCollection( COLL ); // Achtung: Vorhandene Daten werden geloescht! collection.drop(); // Konvertierung von Key/Value-Paaren zu einem MongoDb-Document: Document doc1 = (new Document()).append( "vorname", "Hinz" ).append( "nachname", "Heinrich" ) .append( "groesse", "177" ).append( "haarfarbe", "grün" ); collection.insertOne( doc1 ); // Konvertierung vom JSON-String zum MongoDb-Document: String jsonString = "{ \"vorname\" : \"Kunz\", \"nachname\" : \"Konrad\" }"; collection.insertOne( Document.parse( jsonString ) ); // Kontrolle: assertEquals( 2, collection.count() ); // Suche nach bestimmten Documents, Reduzierung der gelesenenen Felder ("restrict Fields") mit projection(): List<Document> lstDocs = collection.find( Document.parse( "{ vorname: 'Kunz' }" ) ) .projection( Document.parse( "{ '_id': 0, 'vorname' : 1, 'nachname' : 1, 'groesse' : 1 }" ) ) .into( new ArrayList<Document>() ); assertEquals( 1, lstDocs.size() ); Document doc2 = lstDocs.get( 0 ); assertEquals( "Kunz", doc2.getString( "vorname" ) ); assertEquals( "Konrad", doc2.getString( "nachname" ) ); // Konvertierung vom MongoDb-Document zum JSON-String: assertEquals( jsonString, doc2.toJson() ); } MongoDbUtil.zeigeMongoDbsCollsDocs( HOST, PORT ); } }
Die Projektstruktur sieht jetzt so aus (überprüfen Sie es mit tree /F):
[\MeinWorkspace\MongoDbMitJava] |- [src] | |- [main] | | '- [java] | | '- [mongodbmitjava] | | '- MongoDbUtil.java | '- [test] | '- [java] | '- [mongodbmitjava] | '- MongoDbMitJavaTest.java '- pom.xml
Führen Sie bei laufendem MongoDB-Server den JUnit-Modultest aus:
mvn test
Falls Sie alle bisher beschriebenen Schritte nachvollzogen haben, erhalten Sie (mit anderen oids):
... Auflistung der DBs, Collections und Documents in der MongoDB localhost:27017 ... MongoDatabase: local Collections: [startup_log] MongoDatabase: meinmongotest Collections: [personen1, personen2, ...] Collection personen1: { "_id" : { "$oid" : "5649e5f408e8a481730021e0" }, "vorname" : "Anton", "nachname" : "Alfa", "groesse" : 150.0 } { "_id" : { "$oid" : "5649e5f408e8a481730021e1" }, "vorname" : "Berta", "nachname" : "Bravo", "groesse" : 190.0 } { "_id" : { "$oid" : "5649e5f408e8a481730021e2" }, "vorname" : "Cäsar", "nachname" : "Charlie", "groesse" : 170.0 } { "_id" : { "$oid" : "5649e5f408e8a481730021e3" }, "vorname" : "Dora", "nachname" : "Delta", "groesse" : 180.0 } { "_id" : { "$oid" : "5649e5f408e8a481730021e4" }, "vorname" : "Emil", "nachname" : "Echo", "groesse" : 140.0 } Collection personen2: { "_id" : { "$oid" : "5649e73774de9d037c6c0556" }, "vorname" : "Hinz", "nachname" : "Heinrich", "groesse" : "177", "haarfarbe" : "grün" } { "_id" : { "$oid" : "5649e73774de9d037c6c0557" }, "vorname" : "Kunz", "nachname" : "Konrad" } ... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------
JSON Libraries erleichtern die Konvertierung zwischen Java-Objekten und JSON, siehe beispielsweise: JSON Binding with JAX-RS, Top 7 Open-Source JSON-Binding Providers, The Ultimate JSON Library, JSON-B, JSON-P, Jackson, Genson, GSON, MOXy, Xstream.
Das folgende Beispiel demonstriert, wie mit dem Jackson JSON Processor Java-Objekte zu JSON-Strings und weiter zu MongoDB-Documents und umgekehrt konvertiert werden können. Weitergehende Beispiele finden Sie unter: Jackson Wiki, JacksonInFiveMinutes, Jackson Tutorial, Java JSON Tutorial.
Voraussetzung für dieses Beispiel ist das letzte Beispiel MongoDB mit Java.
Fügen Sie im MongoDbMitJava-Projektverzeichnis in der Maven-Projektkonfigurationsdatei pom.xml hinter <dependencies> hinzu:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.6.3</version> </dependency>
Fügen Sie im src\main\java\mongodbmitjava-Verzeichnis eine Entity-Klasse hinzu: Person.java
package mongodbmitjava; public class Person { private String vorname; private String nachname; private int groesse; public Person() {} public Person( String vorname, String nachname, int groesse ) { this.vorname = vorname; this.nachname = nachname; this.groesse = groesse; } public String getVorname() { return vorname; } public String getNachname() { return nachname; } public int getGroesse() { return groesse; } public void setVorname( String vorname ) { this.vorname = vorname; } public void setNachname( String nachname ) { this.nachname = nachname; } public void setGroesse( int groesse ) { this.groesse = groesse; } @Override public String toString() { return "Person={vorname='" + vorname + "', nachname='" + nachname + "', groesse=" + groesse + "}"; } }
Fügen Sie im src\test\java\mongodbmitjava-Testverzeichnis eine JUnit-Modultestklasse hinzu: MongoDbJacksonTest.java
package mongodbmitjava; import static org.junit.Assert.assertEquals; import java.io.IOException; import java.util.*; import org.bson.Document; import org.junit.Test; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.mongodb.MongoClient; import com.mongodb.client.*; /** Konvertierungen zwischen Java-Objekten, JSON-Strings und MongoDB-Documents mit Jackson */ public class MongoDbJacksonTest { static final String HOST = "localhost"; static final int PORT = 27017; static final String DB = "meinmongotest"; static final String COLL = "personen3"; @Test public void testMongoDbMitJackson() throws IOException { try( MongoClient mongo = new MongoClient( HOST, PORT ) ) { MongoDatabase db = mongo.getDatabase( DB ); MongoCollection<Document> collection = db.getCollection( COLL ); ObjectMapper objmapp = new ObjectMapper(); objmapp.setVisibility( PropertyAccessor.FIELD, Visibility.ANY ); // Achtung: Vorhandene Daten werden geloescht! collection.drop(); // Java-Objekte: Person p1 = new Person( "Anna", "S", 163 ); Person p2 = new Person( "Otto", "W", 173 ); // Konvertierung vom Java-Object zum JSON-String und weiter zum MongoDB-Document: collection.insertOne( Document.parse( objmapp.writeValueAsString( p1 ) ) ); collection.insertOne( Document.parse( objmapp.writeValueAsString( p2 ) ) ); // Kontrolle: assertEquals( 2, collection.count() ); List<Document> lstDocs = collection.find( Document.parse( "{ vorname: 'Otto' }" ) ) .projection( Document.parse( "{ '_id': 0 }" ) ) .into( new ArrayList<Document>() ); assertEquals( "[Document{{vorname=Otto, nachname=W, groesse=173}}]", lstDocs.toString() ); // Konvertierung vom MongoDB-Document zum JSON-String und weiter zum Java-Object: Person p3 = objmapp.readValue( lstDocs.get( 0 ).toJson(), Person.class ); assertEquals( "Person={vorname='Otto', nachname='W', groesse=173}", p3.toString() ); } MongoDbUtil.zeigeMongoDbsCollsDocs( HOST, PORT ); } }
Sehen Sie sich die API-Doku an zu der Klasse ObjectMapper.
Das folgende Beispiel demonstriert:
Führen Sie folgende Schritte aus:
Maven muss installiert sein.
Wechseln Sie in Ihr Workspace-Verzeichnis (z.B. \MeinWorkspace) und führen Sie folgende Kommandos aus:
cd \MeinWorkspace
md MongoDbMitSpring
cd MongoDbMitSpring
md src\main\java\mongodbmitspring
tree /F
Erstellen Sie im MongoDbMitSpring-Projektverzeichnis die Maven-Projektkonfigurationsdatei: pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>mongodbmitspring</groupId> <artifactId>MongoDbMitSpring</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>${project.artifactId}</name> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>1.2.8.RELEASE</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> <version>1.2.8.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.8.2.RELEASE</version> </dependency> </dependencies> </project>
Sie können im Maven-Repo nachsehen, ob es mittlerweile neuere Versionen für spring-boot-maven-plugin, spring-boot-starter-data-mongodb und spring-data-mongodb gibt.
Fügen Sie im src\main\java\mongodbmitspring-Verzeichnis eine Entity/Document-Klasse hinzu: Person.java
package mongodbmitspring; import java.time.LocalDate; import java.util.*; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @Document(collection = "personen4") public class Person { @Id private String id; private String vorname; private String nachname; private int groesse; private LocalDate geburtstag; private List<Adresse> adressen; public Person() { } public Person( String vorname, String nachname, int groesse, LocalDate geburtstag, Adresse... adressen ) { this.vorname = vorname; this.nachname = nachname; this.groesse = groesse; this.geburtstag = geburtstag; this.adressen = Arrays.asList( adressen ); } public String getVorname() { return vorname; } public String getNachname() { return nachname; } public int getGroesse() { return groesse; } public LocalDate getGeburtstag() { return geburtstag; } public List<Adresse> getAdressen() { return adressen; } public void setVorname( String vorname ) { this.vorname = vorname; } public void setNachname( String nachname ) { this.nachname = nachname; } public void setGroesse( int groesse ) { this.groesse = groesse; } public void setGeburtstag( LocalDate geburtstag ) { this.geburtstag = geburtstag; } public void setAdressen( List<Adresse> adressen ) { this.adressen = adressen; } @Override public String toString() { return ( geburtstag == null && adressen == null ) ? "Person={vorname='" + vorname + "', nachname='" + nachname + "', groesse=" + groesse + "}" : "Person={vorname='" + vorname + "', nachname='" + nachname + "', groesse=" + groesse + "', geburtstag=" + geburtstag + "', adressen=" + adressen + "}"; } static class Adresse { public String strasse; public int plz; public String ort; public LandEnum land; public Adresse( String strasse, int plz, String ort, LandEnum land ) { this.strasse = strasse; this.plz = plz; this.ort = ort; this.land = land; } @Override public String toString() { return "Adresse={strasse=" + strasse + ", plz=" + plz + ", ort=" + ort + ", land=" + land + "}"; } } static enum LandEnum { DE, AT, CH, LU; } }
Sehen Sie sich die Doku an zu den Annotationen Id und Document.
Fügen Sie im src\main\java\mongodbmitspring-Verzeichnis eine Spring-Data-Repository-Klasse hinzu: PersonRepository.java
package mongodbmitspring; import java.time.LocalDate; import java.util.List; import org.springframework.data.mongodb.repository.MongoRepository; import mongodbmitspring.Person.Adresse; public interface PersonRepository extends MongoRepository<Person,String> { public Person findByVornameAndNachname( String vorname, String nachname ); public List<Person> findByVorname( String vorname ); public List<Person> findByNachname( String nachname ); public List<Person> findByGroesse( int groesse ); public List<Person> findByGroesseGreaterThan( int groesse ); public List<Person> findByGroesseBetween( int from, int to ); public List<Person> findByGeburtstag( LocalDate geburtstag ); public List<Person> findByGeburtstagGreaterThan( LocalDate geburtstag ); public List<Person> findByGeburtstagBetween( LocalDate from, LocalDate to ); public List<Person> findByAdressen( Adresse adresse ); public List<Person> findByAdressenOrt( String ort ); public List<Person> findByAdressenPlz( int plz ); public List<Person> findByAdressenPlzOrderByGroesse( int plz ); }
Beachten Sie, dass die find-Abfragemethoden nicht ausprogrammiert werden müssen.
Sehen Sie sich zum Spring-Data-Repository-Konzept an:
MongoRepository-Interface
Spring Boot Reference Guide, Spring NoSQL Technologies: Spring Data MongoDB Repositories
Spring Data MongoDB Reference Documentation: Working with Spring Data Repositories
Spring Data MongoDB Reference Documentation: MongoDB Repositories
Fügen Sie im src\main\java\mongodbmitspring-Verzeichnis eine ausführbare Klasse hinzu: MongoSpringBeispiel.java
package mongodbmitspring; import java.time.LocalDate; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import mongodbmitspring.Person.Adresse; import mongodbmitspring.Person.LandEnum; @SpringBootApplication public class MongoSpringBeispiel implements CommandLineRunner { private static final Adresse AACHEN = new Adresse( "Markt", 52072, "Aachen", LandEnum.DE ); private static final Adresse KOELN = new Adresse( "Markt", 50667, "Köln", LandEnum.DE ); private static final Adresse WIEN = new Adresse( "Markt", 1010, "Wien", LandEnum.AT ); @Autowired private PersonRepository repo; public static void main( String[] args ) { SpringApplication.run( MongoSpringBeispiel.class, args ); } @Override public void run( String... args ) throws Exception { insertPersonen(); findPersonen(); updatePerson(); repo.deleteAll(); } void insertPersonen() { repo.save( new Person( "Anton", "Alfa", 184, LocalDate.of( 1960, 1, 2 ), WIEN, AACHEN ) ); repo.save( new Person( "Anton", "Beta", 173, LocalDate.of( 1970, 3, 4 ), AACHEN ) ); repo.save( new Person( "Berta", "Beta", 190, LocalDate.of( 1980, 5, 6 ), KOELN ) ); repo.save( new Person( "Cäsar", "Zulu", 175, LocalDate.of( 1990, 7, 8 ), KOELN ) ); } void findPersonen() { LocalDate dt70 = LocalDate.of( 1970, 1, 1 ); LocalDate dt90 = LocalDate.of( 1990, 1, 1 ); printPersonen( "findAll():", repo.findAll() ); printPersonen( "findByVorname('Anton')", repo.findByVorname( "Anton" ) ); printPersonen( "findByNachname('Beta')", repo.findByNachname( "Beta" ) ); printPersonen( "findByGroesse(184)", repo.findByGroesse( 184 ) ); printPersonen( "findByGroesseGreaterThan(175)", repo.findByGroesseGreaterThan( 175 ) ); printPersonen( "findByGroesseBetween(172,176)", repo.findByGroesseBetween( 172, 176 ) ); printPersonen( "findByGeburtstagBetween(1970,1990)", repo.findByGeburtstagBetween( dt70, dt90 ) ); printPersonen( "findByAdressen(Aachen)", repo.findByAdressen( AACHEN ) ); printPersonen( "findByAdressenOrt('Wien')", repo.findByAdressenOrt( "Wien" ) ); printPersonen( "findByAdressenPlz(50667)", repo.findByAdressenPlz( 50667 ) ); printPersonen( "findByAdressenPlzOrderByGroesse(50667)", repo.findByAdressenPlzOrderByGroesse( 50667 ) ); } void updatePerson() { Person antonAnnet = repo.findByVornameAndNachname( "Anton", "Alfa" ); antonAnnet.setVorname( "Annet" ); repo.save( antonAnnet ); printPersonen( "update('Anton Alfa' -> 'Annet Alfa')", repo.findAll() ); System.out.println(); } static void printPersonen( String titel, List<Person> personen ) { System.out.println( "\n" + titel + ":" ); personen.forEach( System.out::println ); } }
Beachten Sie, dass die Person-Java-Entity-Objekte inklusive Enum und Listen von Objekten direkt gespeichert und gelesen werden können,
ohne Umwandlung nach und von JSON. Diese Umwandlung wird auch ODM (Object Document Mapping) genannt.
Sehen Sie sich die Doku an zu den Annotationen
SpringBootApplication und
Autowired,
sowie dem Interface
CommandLineRunner
und der Klasse
SpringApplication.
Die Projektstruktur sieht jetzt so aus (überprüfen Sie es mit tree /F):
[\MeinWorkspace\MongoDbMitSpring] |- [src] | '- [main] | '- [java] | '- [mongodbmitspring] | |- MongoSpringBeispiel.java | |- Person.java | '- PersonRepository.java '- pom.xml
Durch das spring-boot-maven-plugin wird eine ausführbare jar-Datei erzeugt, welche alle benötigten Abhängigkeiten beinhaltet.
Führen Sie bei laufendem MongoDB-Server aus:
mvn clean package
java -jar target/MongoDbMitSpring.jar
Sie erhalten:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.2.8.RELEASE) ... --- [main] mongodbmitspring.MongoSpringBeispiel : Starting MongoSpringBeispiel ... (D:\MeinWorkspace\MongoDbMitSpring... ... --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext... ... --- [main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup findAll():: Person={vorname='Anton', nachname='Alfa', groesse=184', geburtstag=1960-01-02', adressen=[Adresse={strasse=Markt, plz=1010, ort=Wien, land=AT}, Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} Person={vorname='Anton', nachname='Beta', groesse=173', geburtstag=1970-03-04', adressen=[Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} Person={vorname='Berta', nachname='Beta', groesse=190', geburtstag=1980-05-06', adressen=[Adresse={strasse=Markt, plz=50667, ort=Köln, land=DE}]} Person={vorname='Cäsar', nachname='Zulu', groesse=175', geburtstag=1990-07-08', adressen=[Adresse={strasse=Markt, plz=50667, ort=Köln, land=DE}]} findByVorname('Anton'): Person={vorname='Anton', nachname='Alfa', groesse=184', geburtstag=1960-01-02', adressen=[Adresse={strasse=Markt, plz=1010, ort=Wien, land=AT}, Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} Person={vorname='Anton', nachname='Beta', groesse=173', geburtstag=1970-03-04', adressen=[Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} findByNachname('Beta'): Person={vorname='Anton', nachname='Beta', groesse=173', geburtstag=1970-03-04', adressen=[Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} Person={vorname='Berta', nachname='Beta', groesse=190', geburtstag=1980-05-06', adressen=[Adresse={strasse=Markt, plz=50667, ort=Köln, land=DE}]} findByGroesse(184): Person={vorname='Anton', nachname='Alfa', groesse=184', geburtstag=1960-01-02', adressen=[Adresse={strasse=Markt, plz=1010, ort=Wien, land=AT}, Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} findByGroesseGreaterThan(175): Person={vorname='Anton', nachname='Alfa', groesse=184', geburtstag=1960-01-02', adressen=[Adresse={strasse=Markt, plz=1010, ort=Wien, land=AT}, Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} Person={vorname='Berta', nachname='Beta', groesse=190', geburtstag=1980-05-06', adressen=[Adresse={strasse=Markt, plz=50667, ort=Köln, land=DE}]} findByGroesseBetween(172,176): Person={vorname='Anton', nachname='Beta', groesse=173', geburtstag=1970-03-04', adressen=[Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} Person={vorname='Cäsar', nachname='Zulu', groesse=175', geburtstag=1990-07-08', adressen=[Adresse={strasse=Markt, plz=50667, ort=Köln, land=DE}]} findByGeburtstagBetween(1970,1990): Person={vorname='Anton', nachname='Beta', groesse=173', geburtstag=1970-03-04', adressen=[Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} Person={vorname='Berta', nachname='Beta', groesse=190', geburtstag=1980-05-06', adressen=[Adresse={strasse=Markt, plz=50667, ort=Köln, land=DE}]} findByAdressen(Aachen): Person={vorname='Anton', nachname='Alfa', groesse=184', geburtstag=1960-01-02', adressen=[Adresse={strasse=Markt, plz=1010, ort=Wien, land=AT}, Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} Person={vorname='Anton', nachname='Beta', groesse=173', geburtstag=1970-03-04', adressen=[Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} findByAdressenOrt('Wien'): Person={vorname='Anton', nachname='Alfa', groesse=184', geburtstag=1960-01-02', adressen=[Adresse={strasse=Markt, plz=1010, ort=Wien, land=AT}, Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} findByAdressenPlz(50667): Person={vorname='Berta', nachname='Beta', groesse=190', geburtstag=1980-05-06', adressen=[Adresse={strasse=Markt, plz=50667, ort=Köln, land=DE}]} Person={vorname='Cäsar', nachname='Zulu', groesse=175', geburtstag=1990-07-08', adressen=[Adresse={strasse=Markt, plz=50667, ort=Köln, land=DE}]} findByAdressenPlzOrderByGroesse(50667): Person={vorname='Cäsar', nachname='Zulu', groesse=175', geburtstag=1990-07-08', adressen=[Adresse={strasse=Markt, plz=50667, ort=Köln, land=DE}]} Person={vorname='Berta', nachname='Beta', groesse=190', geburtstag=1980-05-06', adressen=[Adresse={strasse=Markt, plz=50667, ort=Köln, land=DE}]} update('Anton Alfa' -> 'Annet Alfa'): Person={vorname='Annet', nachname='Alfa', groesse=184', geburtstag=1960-01-02', adressen=[Adresse={strasse=Markt, plz=1010, ort=Wien, land=AT}, Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} Person={vorname='Anton', nachname='Beta', groesse=173', geburtstag=1970-03-04', adressen=[Adresse={strasse=Markt, plz=52072, ort=Aachen, land=DE}]} Person={vorname='Berta', nachname='Beta', groesse=190', geburtstag=1980-05-06', adressen=[Adresse={strasse=Markt, plz=50667, ort=Köln, land=DE}]} Person={vorname='Cäsar', nachname='Zulu', groesse=175', geburtstag=1990-07-08', adressen=[Adresse={strasse=Markt, plz=50667, ort=Köln, land=DE}]}