Conectar Java con MongoDB - Ejemplo CRUD

De ChuWiki


Para conectar Java con MongoDB necesitas el driver mongodb-driver-sync.jar para crear un MongoClient. A partir de esta clase se obtiene acceso a las colecciones de la base de datos con las que podremos luego ejecutar las operaciones CRUD (Create, Read, Update y Delete).

Veamos un ejemplo, tienes el código completo en MongoDBSampleMain.java.

Descarga del driver de MongoDB para Java[editar]

Como hemos comentado, en nuestro proyecto necesitamos mongodb-driver-sync.jar. Si nuestro proyecto es Maven, bastaría añadir la dependencia correspondiente en el fichero pom.xml.

<!-- https://mvnrepository.com/artifact/org.mongodb/mongodb-driver-sync -->
<dependency>
   <groupId>org.mongodb</groupId>
   <artifactId>mongodb-driver-sync</artifactId>
   <version>4.10.2</version>
</dependency>

Cuando ejecutemos el programa de prueba, el driver indica que no hay un sistema de log compatible con slf4j que es el que usa. Funciona sin problemas, pero no veremos el log. Si queremos verlo, debemos añadir también una dependencia de un sistema de log compatible, como puede ser logback-classic.

<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
   <groupId>ch.qos.logback</groupId>
   <artifactId>logback-classic</artifactId>
   <version>1.4.11</version>
</dependency>

Aquí tienes el fichero pom.xml completo.

Hay otros drivers de mongodb para Java y varias versiones. Para este ejemplo sencillo hemos usado el último disponible para este. En Descargar Driver de MongoDB para Java puedes ver todas las opciones de driver que hay y la compatibilidad de versiones tanto con la versión de Java como con la instalación de mongodb que estés usando.

Instalación de MongoDB[editar]

Para ejecutar el ejemplo necesitas tener acceso a un nodo de MongoDB instalado y ejecutándose. No vamos a detallar aquí la instalación. Puedes seguir los pasos de instalación en la página oficial de MongoDB. O si controlas docker, puedes levantar una imagen de mongo en docker.

En ejemplo suponemos que no hay usuario y password de acceso y que está instalado en la IP 172.17.0.2 y atiende al puerto por defecto 27017. Puedes cambiar fácilmente todo esto en el código si tienes usuario y password, otra IP u otro puerto.

Establecer conexión con MongoDB desde Java[editar]

La forma de establecer la conexión es la siguiente

// Cadena de conexion con la base de datos MongoDB
String uri = "mongodb://172.17.0.2:27017";

// Se abre la conexión con MongoDB
try (MongoClient mongoClient = MongoClients.create(uri)) {
   ...
}

La cadena de conexión admite el formato "mongodb://<username>:<password>@<host>:<puerto>". Username, password y puerto son opcionales. El puerto por defecto es 27017. Puedes cambiar los datos con los que tengas en tu base de datos MongoDB.

Metemos la creación en un bloque try-with-resources, de esta forma evitamos tener que cerrar explícitamente la conexión cuando terminemos con ella.

Crear o acceder a la base de datos MongoDB[editar]

Una vez tenemos la conexión con MongoDB, podemos acceder a sus bases de datos de la siguiente forma

// Obtener o crear una base de datos MongoDB desde Java
MongoDatabase database = mongoClient.getDatabase("My_Data_Base");

Esto permite acceder, o crear si no existe, la base de datos "My_Data_Base". El nombre puede ser el que queramos siempre que tenga caracteres váidos para un nombre de base de datos de mongo.

Crear o acceder a las coleciones de una base de datos MongoDB[editar]

En la base de datos de MongoDB puede haber colecciones, equivalentes a las tablas de una base de datos relacional normal. Podemos acceder o crear estas colecciones con el siguiente código

// Obtener o crear una colección MongoDB
MongoCollection<Document> collection = database.getCollection("my_collection");

Esto permite acceder, o crear si no existe, la colección "my_collection". El nombre puede ser cualquiera, siempre que tenga caracters admitidos como nombre de una colección en MongoDB.

Esta es la forma más simple que nos obliga en adelante a usar documentos BSON (org.bson.Document) como datos. Existe una forma de obtener la base de datos de forma que podamos usar directamente nuestros objetos Java de datos (POJO o Plain Old Java Objects). Puedes ver como hacer esta configuración y usarla luego en Java POJOs con MongoDB.

Operaciones CRUD sobre la colección de MongoDB[editar]

Una vez tenemos la colección, podemos hacer en ella las operaciones CRUD habituales. En estos ejemplos vamos a hacerlos con documentos bson (org.bson.Document) que en el fondo son como Map de Java, es decir, admiten parejas clave/valor. Podríamos hacerlo con objetos Java normales (POJO). Para ello, debemos configurar el driver de MongoDB con un PojoCodecProvider. Los métodos serían similares a los aquí mostrados, pero obtendríamos una objeto Java concreto nuestro en vez de un documento bson.

Insertar documentos en una colección de MongoDB[editar]

Para la inserción, tenemos método para insertar registros (en MongoDB se llaman documentos) de uno en un o bien varios de golpe. El código es el siguiente

// Insertar algún documento en la colección
Document data = new Document().append("name", "Pedro").append("age", 22);
InsertOneResult insertOneResult = collection.insertOne(data);
System.out.println(insertOneResult.getInsertedId());

// Insertar varios documentos de golpe en la colección
List<Document> severalData = new ArrayList<>();
severalData.add(new Document().append("name", "Elena").append("age", 33));
severalData.add(new Document().append("name", "Ana").append("age", 41));
InsertManyResult insertManyResult = collection.insertMany(severalData);
System.out.println(insertManyResult.getInsertedIds());

El docueento a insertar lo creamos con new Document() y vamos llamando a append(key,value) para ir insertándole las distintas parejas clave/valor que queramos que tenga dicho documento.

La llamada a collection.insertOne(document) nos permite insertar los documentos de uno en uno. La llamada a collection.insertMany(List<Document>) nos permite insertar varios documentos de golpe.

Ambas llamdas devuelven un resultado en el que podemos consultar los identificadores de MongoDB para los documentos recién insertados. Sería el equivalente a las claves primarias de una base de datos relacional.

Consultar documentos en una colección de MongoDB[editar]

Para la consulta en la colección de MongoDB usamos find(), al que podemos poner un filtro como parámetro si queremos buscar algún resultado concreto. El código sería el siguiente

// Obtener todos los documentos
FindIterable<Document> allCollection = collection.find();
System.out.println("\n--- find() result ---");
allCollection.forEach(document -> System.out.println(document));

// Consultar por un campo del documento
Bson filter = Filters.eq("name", "Pedro");
FindIterable<Document> elementsFound = collection.find(filter);
System.out.println("\n--- find(filter) result ---");
elementsFound.forEach(document -> System.out.println(document));

El método find() nos devuelve un iterador con todos los documentos de la colección.

Si quermos un filtro, podemos usar la clase Filters de MongoDB. Tiene métodos de todo tipo para construir filtros: comparaciones, geográficos, and, or, etc. En este ejemplo usamos uno simple, eq(), que es equivalente a "igual" (abreviatura de "equals" en inglés). A eq() le pasamos la clave con la que tiene que comprar y el valor con el que tiene que ser igual. En el ejemplo de la llamada, nos devolverá el documento cuya clave "name" es "Pedro".

Modificación de documentos en una colección de MongoDB[editar]

Para modificar documentos tenemos los métodos updateOne() y updateMany() de collection. El siguente sería un ejemplo

Bson newAge = Updates.set("age", 23);
UpdateResult updateOne = collection.updateOne(filter, newAge);
System.out.println(updateOne.getMatchedCount());

Ambos métodos admiten un filtro para ver qué parametros modificar y un segundo parámetro que indica las moficaciones a realizar. El filtro hemos reutilizado el anterior de la consulta, es decir, modificamos a "Pedro".

Las modificaciones debemos obtenerlas con la clase Updates. Esta clase tiene método que permite añadir claves al documento, borrarlas, modificar valores, etc, etc. En nuestro ejemplo, usamos set() para camiar (o insertar si no existe) el valor de la clave "age" a 23.

La llamada devuelve un resultado al que podemos consultar cuántos documentos han sido modificados en la colección.

Borrado de documentos en una colección de MongoDB[editar]

Para borrado tenemos algo similar a la inserción. Podemos borrar un documento o muchos, indicando el filtro de borrado. Si el filtro está vacío, borra todos. El código sería el siguiente

// Borrar por un campo
DeleteResult deleteResult = collection.deleteMany(filter);
System.out.println("\n--- Number of deleted elements with filter ---");
System.out.println(deleteResult.getDeletedCount());

// Borrar todos los documentos de la colección
deleteResult = collection.deleteMany(Filters.empty());
System.out.println("\n--- Number of deleted elements with empty filter ---");
System.out.println(deleteResult.getDeletedCount());

Para borrar uno, reutilizamos el filtro que habíamos creado en la parte de consulta, es decir, filter, que borrará a "Pedro".

Para el borrado de muchos, hemos creado un filtro vacío con Filter.empty(). Esto borrará todos los documentos de la colección. Si el filtro no estuviera vacío, borraría sólo los que cumplan el filtro.

Ambos método devuelven un resultado en el que podemos consultar cuántos documentos se han borrado de la colección.

Eliminar la colección de MongoDB[editar]

El borrado anterior borra documentos de la colección, pero no la colección en sí misma. Podemos tener la colección vacía, sin elementos. El método drop() elimina la colección de la base de datos.

// Eliminar la coleccion de MongoDB
collection.drop();

Eliminar la base de datos de MongoDB[editar]

Para eliminar totalmente la base de datos de MongoDB, se usa el método drop() de MongoDatabase

// Eliminar la base de datos de MongoDB
database.drop();

Cerrar la conexión con MongoDB[editar]

Una vez terminemos, debemos cerrar la conexión llamando a close().

// Cierre de la conexión con MongoDB. No es necesario puesto que usamos try-with-resources
// mongoClient.close();

En nuestro ejemplo no es necesario puesto que usamos try-with-resources, como comentamos al abrirla.