1. Resumen
Este artículo será una introducción rápida y práctica a Spring Data MongoDB.
Repasaremos los conceptos básicos utilizando tanto la MongoTemplate así como MongoRepository , con ejemplos prácticos para ilustrar cada operación.
Lectura adicional:
Soporte geoespacial en MongoDB
Eche un vistazo a cómo almacenar, indexar y buscar datos geoespaciales con MongoDBLeer más →Pruebas de integración de Spring Boot con MongoDB incorporado
Aprenda a usar la solución MongoDB integrada de Flapdoodle junto con Spring Boot para ejecutar las pruebas de integración de MongoDB sin problemas. Leer más →2. Plantilla Mongo y MongoRepository
La Plantilla Mongo sigue el patrón de plantilla estándar en Spring y proporciona una API básica lista para usar para el motor de persistencia subyacente.
El repositorio sigue el enfoque centrado en Spring Data y viene con operaciones de API más flexibles y complejas, basadas en los patrones de acceso bien conocidos en todos los proyectos de Spring Data.
Para ambos, debemos comenzar definiendo la dependencia, por ejemplo, en el pom.xml , con Maven:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
Para verificar si se ha lanzado alguna nueva versión de la biblioteca, haga un seguimiento de los lanzamientos aquí.
3. Configuración para MongoTemplate
3.1. Configuración XML
Comencemos con la configuración XML simple para la plantilla de Mongo:
<mongo:mongo-client id="mongoClient" host="localhost" />
<mongo:db-factory id="mongoDbFactory" dbname="test" mongo-client-ref="mongoClient" />
Primero necesitamos definir el bean de fábrica responsable de crear instancias de Mongo.
A continuación, debemos definir (y configurar) el bean de plantilla:
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongoDbFactory"/>
</bean>
Y finalmente, necesitamos definir un posprocesador para traducir cualquier MongoExceptions lanzado en @Repository clases anotadas:
<bean class=
"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
3.2. Configuración Java
Ahora creemos una configuración similar usando la configuración de Java extendiendo la clase base para la configuración de MongoDB AbstractMongoConfiguration :
@Configuration
public class MongoConfig extends AbstractMongoClientConfiguration {
@Override
protected String getDatabaseName() {
return "test";
}
@Override
public MongoClient mongoClient() {
ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/test");
MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
.applyConnectionString(connectionString)
.build();
return MongoClients.create(mongoClientSettings);
}
@Override
public Collection getMappingBasePackages() {
return Collections.singleton("com.baeldung");
}
}
Tenga en cuenta que no necesitamos definir MongoTemplate bean en la configuración anterior ya que ya está definido en AbstractMongoClientConfiguration .
También podemos usar nuestra configuración desde cero sin extender AbstractMongoClientConfiguration :
@Configuration
public class SimpleMongoConfig {
@Bean
public MongoClient mongo() {
ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/test");
MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
.applyConnectionString(connectionString)
.build();
return MongoClients.create(mongoClientSettings);
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), "test");
}
}
4. Configuración para MongoRepository
4.1. Configuración XML
Para hacer uso de repositorios personalizados (ampliando el MongoRepository ), necesitamos continuar con la configuración desde la sección 3.1. y configurar los repositorios:
<mongo:repositories
base-package="com.baeldung.repository" mongo-template-ref="mongoTemplate"/>
4.2. Configuración Java
Del mismo modo, nos basaremos en la configuración que ya creamos en la sección 3.2. y agregue una nueva anotación a la mezcla:
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
4.3. Crear el Repositorio
Después de la configuración, necesitamos crear un repositorio, extendiendo el MongoRepository existente interfaz:
public interface UserRepository extends MongoRepository<User, String> {
//
}
Ahora podemos conectar automáticamente este UserRepository y usar operaciones de MongoRepository o agregar operaciones personalizadas.
5. Uso de MongoTemplate
5.1. Insertar
Comencemos con la operación de inserción y una base de datos vacía:
{
}
Ahora si insertamos un nuevo usuario:
User user = new User();
user.setName("Jon");
mongoTemplate.insert(user, "user");
la base de datos se verá así:
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
5.2. Guardar – Insertar
El guardar La operación tiene una semántica de guardar o actualizar:si hay una identificación, realiza una actualización y, si no, realiza una inserción.
Veamos la primera semántica:la inserción.
Este es el estado inicial de la base de datos:
{
}
Cuando ahora guardamos un nuevo usuario:
User user = new User();
user.setName("Albert");
mongoTemplate.save(user, "user");
la entidad se insertará en la base de datos:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Albert"
}
A continuación, veremos la misma operación:guardar — con actualización de semántica.
5.3. Guardar – Actualizar
Veamos ahora guardar con semántica de actualización, operando en una entidad existente:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"
}
Cuando ahorramos el usuario existente, lo actualizaremos:
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
mongoTemplate.save(user, "user");
La base de datos se verá así:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Podemos ver que en este ejemplo particular, guardar usa la semántica de update porque usamos un objeto con _id dado .
5.4. Actualizar primero
actualizar primero actualiza el primer documento que coincide con la consulta.
Comencemos con el estado inicial de la base de datos:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
}
]
Cuando ahora ejecutamos updateFirst :
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);
solo se actualizará la primera entrada:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "James"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
}
]
5.5. Actualizar Múltiples
Actualizar Múltiples actualiza todos los documentos que coinciden con la consulta dada.
Primero, este es el estado de la base de datos antes de hacer updateMulti :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
}
]
Ahora ejecutemos updateMulti operación:
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);
Ambos objetos existentes se actualizarán en la base de datos:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Victor"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Victor"
}
]
5.6. Buscar y modificar
Esta operación funciona como updateMulti , pero devuelve el objeto antes de que se modificara.
Primero, este es el estado de la base de datos antes de llamar a findAndModify :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Veamos el código de operación real:
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);
El objeto de usuario devuelto tiene los mismos valores que el estado inicial en la base de datos.
Sin embargo, este es el nuevo estado en la base de datos:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.7. Insertar
El trastorno funciona en buscar y modificar otra cosa crear semántica :si el documento coincide, actualícelo o cree un nuevo documento combinando la consulta y el objeto de actualización.
Comencemos con el estado inicial de la base de datos:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Ahora vamos a ejecutar upsert :
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);
Este es el estado de la base de datos después de la operación:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.8. Eliminar
Veremos el estado de la base de datos antes de llamar a remove :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Ahora ejecutemos remove :
mongoTemplate.remove(user, "user");
El resultado será el esperado:
{
}
6. Uso de MongoRepository
6.1. Insertar
Primero, veremos el estado de la base de datos antes de ejecutar insertar :
{
}
Ahora insertaremos un nuevo usuario:
User user = new User();
user.setName("Jon");
userRepository.insert(user);
Y aquí está el estado final de la base de datos:
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
Tenga en cuenta que la operación funciona igual que insertar en la Plantilla Mongo API.
6.2. Guardar – Insertar
Del mismo modo, guardar funciona igual que guardar operación en MongoTemplate API.
Comencemos mirando la semántica de inserción de la operación.
Este es el estado inicial de la base de datos:
{
}
Ahora ejecutamos el save operación:
User user = new User();
user.setName("Aaron");
userRepository.save(user);
Esto da como resultado que el usuario se agregue a la base de datos:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Aaron"
}
Observe de nuevo cómo guardar funciona con insertar semántica porque estamos insertando un nuevo objeto.
6.3. Guardar – Actualizar
Veamos ahora la misma operación pero con actualizar semántica.
Primero, este es el estado de la base de datos antes de ejecutar el nuevo guardar :
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"81*6
}
Ahora ejecutamos la operación:
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
userRepository.save(user);
Finalmente, aquí está el estado de la base de datos:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Observe de nuevo cómo guardar funciona con actualizar semántica porque estamos usando un objeto existente.
6.4. Eliminar
Este es el estado de la base de datos antes de llamar a delete :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Ejecutemos eliminar :
userRepository.delete(user);
Y aquí está nuestro resultado:
{
}
6.5. Encuentre uno
A continuación, este es el estado de la base de datos cuando findOne se llama:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
Ahora ejecutemos findOne :
userRepository.findOne(user.getId())
Y el resultado devolverá los datos existentes:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
6.6. Existe
El estado de la base de datos antes de llamar existe :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Harris"
}
Ahora vamos a ejecutar existe , que por supuesto devolverá verdadero :
boolean isExists = userRepository.exists(user.getId());
6.7. Buscar todo Con Ordenar
El estado de la base de datos antes de llamar a findAll :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Ahora ejecutemos findAll con Ordenar :
List<User> users = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));
El resultado será ordenado por nombre en orden ascendente :
[
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
]
6.8. Buscar todo Con Paginable
El estado de la base de datos antes de llamar a findAll :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Ahora ejecutemos findAll con una solicitud de paginación:
Pageable pageableRequest = PageRequest.of(0, 1);
Page<User> page = userRepository.findAll(pageableRequest);
List<User> users = pages.getContent();
Los usuarios resultantes la lista será de un solo usuario:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
7. Anotaciones
Finalmente, repasemos también las anotaciones simples que Spring Data usa para impulsar estas operaciones API.
El nivel de campo @Id la anotación puede decorar cualquier tipo, incluso larga y cadena :
@Id
private String id;
Si el valor de @Id el campo no es nulo, se almacena en la base de datos tal cual; de lo contrario, el convertidor asumirá que queremos almacenar un ObjectId en la base de datos (ya sea ObjectId , Cadena o Entero grande trabajo).
A continuación, veremos @Document :
@Document
public class User {
//
}
Esta anotación simplemente marca una clase como un objeto de dominio que debe persistir en la base de datos, además de permitirnos elegir el nombre de la colección que se utilizará.