Overview
En este tutorial, puedes aprender cómo usar Spring Data MongoDB con el controlador de Java para realizar inserciones masivas de alto rendimiento en una aplicación Spring Boot.
Spring Data MongoDB
Spring Data MongoDB es el mapeador de documentos de objetos (ODM) oficial de Spring Data para MongoDB. Permite interactuar con MongoDB mediante objetos Java (POJO) y abstracción de repositorios. Admite funciones específicas de MongoDB, como consultas dinámicas, indexación y mapeo de documentos anidados, a la vez que reduce el código repetitivo, como el manual. find() y update() llamadas.
Bota de primavera
Spring Boot es un framework diseñado sobre el Spring Framework. Agrega autoconfiguración, valores por defecto y funcionalidades listas para producción para simplificar la construcción de aplicaciones Java basadas en Spring, incluida la integración con Spring Data MongoDB. Para obtener más información, consulta la Documentación de Spring Boot.
Inyección de dependencias
La inyección de dependencias (DI) es un principio fundamental del marco Spring. Permite que el contenedor de Spring cree y administre objetos llamados beans y luego los inyecte en otros beans que los utilizan. Esto es diferente del desarrollo orientado a objetos típico, donde las clases son responsables de inicializar y construir los objetos que utilizan.
Para obtener más información sobre la inyección de dependencias, consulte la página Inyección de dependencias de la documentación de Spring Framework.
Spring Data BulkOperations Interface
BulkOperations es una interfaz Spring Data MongoDB que contiene una lista de operaciones de escritura que pueden aplicarse a tu base de datos. Puede gestionar cualquier combinación de las siguientes operaciones, que se corresponden con operaciones similares en el controlador Java de MongoDB:
insertupdateOneupdateManyreplaceOnedeleteOnedeleteManyupsert
Un BulkOperation puede ser ordenado o desordenado. Las operaciones masivas ordenadas se ejecutan secuencialmente y, si se detecta un error, devuelven un código de error. Las operaciones desordenadas se ejecutan en paralelo, lo que significa que suelen ser más rápidas. Sin embargo, debe comprobar manualmente si se produjeron errores durante las operaciones.
Para obtener más información sobre las operaciones masivas, consulta los siguientes recursos:
BulkOperations en la documentación de la API de Spring Framework
Operaciones de escritura masiva en esta guía
Operaciones de escritura masiva en el manual del MongoDB Server
Tutorial
Puedes encontrar la aplicación de muestra completa para este tutorial en el repositorio de GitHub del Proyecto de muestra SpringDataBulkInsert.
Nota
Importaciones no especificadas
Esta página no incluye las instrucciones de importación necesarias para los archivos del tutorial. Consulta el repositorio de GitHub para obtener los archivos completos.
Requisitos previos
Asegúrese de tener los siguientes componentes instalados y configurados antes de iniciar este tutorial:
Un clúster de MongoDB Atlas. Para crear uno, ve a Primeros pasos con Atlas.
Una nueva aplicación Spring Boot
Agregar dependencias
Asegúrate de usar una versión de Spring Data MongoDB que sea compatible con el MongoDB Java Driver y las versiones de Java que estás utilizando. Para obtener especificaciones de compatibilidad, consulta la página Requirements de la documentación de Spring Data MongoDB, y la página Compatibility de esta guía.
Nota
Si utilizaste Spring Initializr o un clon del proyecto de muestra Spring Boot para crear tu proyecto, ya se ha tenido en cuenta la compatibilidad de versiones, y el componente spring-boot-starter-data-mongodb ya estará incluido en tu archivo pom.xml.
Se debe añadir las siguientes dependencias al archivo pom.xml:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> <version>3.2.5 </version> </dependency> <dependency> <groupId>net.datafaker</groupId> <artifactId>datafaker</artifactId> <version>2.4.3</version> </dependency>
La dependencia datafaker se utiliza para generar una gran cantidad de objetos Product que se utilizan en la operación de escritura masiva.
Configura tu MongoClient
La clase MongoConfig contiene la configuración para el objeto MongoClient que permitirá que el marco de trabajo de Spring Data interactúe con el MongoDB Server y establece otras opciones de configuración. Para obtener más información sobre las opciones de configuración, consulta la página Specify Connection Options de esta guía.
Esta aplicación utiliza @Configuration anotaciones para clases, @Bean anotaciones para métodos y @Value anotaciones para la conversión de parámetros. Estas anotaciones permiten que el contenedor Spring Inversion of Control (IoC) gestione objetos. Para obtener una explicación detallada de estas anotaciones, consulta las siguientes secciones de la guía del marco de trabajo Spring Data:
@Configurationy@Beananotaciones: Configuración de contenedor basada en Java@Valueanotaciones: Usar @Value
Crea un archivo MongoConfig.java y agrega las siguientes clases de configuración y plantilla para configurar tu conexión a MongoDB:
public class MongoConfig { private String uri; private String databaseName; public MongoClient mongoClient() { ConnectionString connectionString = new ConnectionString(uri); MongoClientSettings mongoClientSettings = MongoClientSettings.builder() .applyConnectionString(connectionString) .build(); return MongoClients.create(mongoClientSettings); } public MongoTemplate mongoTemplate() throws Exception { return new MongoTemplate(mongoClient(), databaseName); } }
Nota
API vs Interfaz
Esta implementación usa la API MongoTemplate, en lugar de extender una interfaz de repositorio Spring Data como MongoRepository, para permitir un control detallado sobre las operaciones en bloque.
Establece los valores de tu cadena de conexión (mongodb.uri), nombre de la base de datos (mongodb.database) y el conteo de operaciones masivas (documentCount) en tu archivo application.properties:
mongodb.database=bulk mongodb.uri=<connection string> documentCount=25000
Este tutorial utiliza una base de datos llamada bulk y 25 crea,000 documentos para guardar. Reemplace <connection
string> el marcador con la cadena de conexión de su implementación de Atlas. Para obtener más información, consulte la sección "Crear una cadena de conexión" de esta guía.
Mapea su objeto a un documento
Mapear una clase a una colección permite que el contenedor IoC de Spring almacene objetos como documentos MongoDB. Puedes usar la anotación @Document para especificar a qué colección se asigna una clase. Para obtener más información sobre cómo mapear objetos a documentos MongoDB, consulta la sección Descripción general de la anotación de mapeo de la documentación de Spring Data MongoDB.
La anotación @Id en el siguiente código indica que el campo del objeto id se asigna al campo del documento _id, que se utiliza como identificador único en los documentos de MongoDB. Puedes elegir cualquier campo de cualquier tipo, excepto arreglos, como identificador único. Para obtener más información, consulta la sección Cómo se gestiona el campo _id en la capa de mapeo de la documentación de Spring Data MongoDB.
Utiliza el siguiente código para crear un archivo Product.java que defina tu clase Product y la asocie a tu colección products:
public class Product { private static final Logger LOG = LoggerFactory.getLogger(Product.class); private String id; private String name; private int qty; private double price; private Date available; private Date unavailable; private String skuId; public Product(String name, int qty, double price, Date available, Date unavailable, String skuId) { this.name = name; this.qty = qty; this.price = price; this.available = available; this.unavailable = unavailable; this.skuId = skuId; } public static List<Product> randomProducts(int count) { Faker faker = new Faker(); Random rand = new Random(); List<Product> retProds = new ArrayList<>(count); for (int i = 0; i < count; ++i) { Product product = new Product(faker.animal().name(), 1 + rand.nextInt(998), 10.0 + rand.nextInt(9999), new Date(), new Date(), faker.idNumber().valid()); retProds.add(product); } return retProds; } // Getters and setters }
La clase Product incluye un método estático que genera un arreglo de objetos Product. También puedes definir getters y setters para los campos.
Define un repositorio para almacenar tus productos
El objeto ProductRepository gestionará una colección de objetos Product. Tu objeto ProductRepository debe estar inyectado con el bean MongoTemplate generado en la clase MongoConfig. Al utilizar la anotación @Autowired con un constructor que incluye mongoTemplate como argumento, el contenedor de Spring utiliza la inyección de constructores para inyectar una dependencia de mongoTemplate. Para obtener más información sobre la inyección por constructor, consulta la sección Inyección de dependencias basada en constructor de la documentación de Spring Framework.
Use el siguiente código para crear el archivo ProductRepository.java y defina su clase ProductRepository para gestionar una colección de objetos Product:
public class ProductRepository { private static final Logger LOG = LoggerFactory .getLogger(ProductRepository.class); private final MongoTemplate mongoTemplate; public ProductRepository(MongoTemplate mongoTemplate){ this.mongoTemplate = mongoTemplate; } public void updateProductQuantity(String name, int newQuantity) { Query query = new Query(Criteria.where("name").is(name)); Update update = new Update(); update.set("quantity", newQuantity); UpdateResult result = mongoTemplate.updateFirst(query, update, Product.class); if (result == null) LOG.error("No documents updated"); else LOG.info(result.getModifiedCount() + " document(s) updated.."); } public int bulkInsertProducts(int count) { LOG.info("Dropping collection..."); mongoTemplate.dropCollection(Product.class); LOG.info("Dropped!"); Instant start = Instant.now(); mongoTemplate.setWriteConcern(WriteConcern.W1.withJournal(true)); List<Product> productList = Product.randomProducts(count); BulkOperations bulkInsertion = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, Product.class); bulkInsertion.insert(productList); BulkWriteResult bulkWriteResult = bulkInsertion.execute(); LOG.info("Bulk insert of " + bulkWriteResult.getInsertedCount() + " documents completed in " + Duration.between(start, Instant.now()).toMillis() + " milliseconds"); return bulkWriteResult.getInsertedCount(); } }
El método bulkInsertProducts() utiliza inserciones masivas desordenadas, lo que puede mejorar el rendimiento al no garantizar el orden de las operaciones.
Realizar una operación masiva
La clase principal de la aplicación activa el ProductRepository para generar el número especificado de objetos Product y guardarlos en la base de datos MongoDB. Utiliza la anotación @Autowired para inyectar un ProductRepository, e implementa un registro de actividades.
Agregue el siguiente código a su clase principal para ejecutar su aplicación:
public class SpringDataBulkInsertApplication implements CommandLineRunner { private int count; private static final Logger LOG = LoggerFactory .getLogger(SpringDataBulkInsertApplication.class); private ProductRepository repository; public static void main(String[] args) { SpringApplication.run(SpringDataBulkInsertApplication.class, args); } public void run(String... args) throws Exception { repository.bulkInsertProducts(count); LOG.info("End run"); System.exit(0); } }
Conclusión
Spring Data MongoDB proporciona una abstracción de alto nivel para trabajar con MongoDB. Puede simplificar la arquitectura de la aplicación al permitir la inyección automática de dependencias, lo que elimina la necesidad de configuración manual del cliente y el manejo complejo de las queries. Al reducir el código redundante y permitir el acceso orientado a objetos a los datos, puede agilizar el acceso a los datos y fomentar una clara separación de responsabilidades.
Más recursos
Para obtener más información sobre los marcos Spring y Spring Data MongoDB, consulte los siguientes recursos:
Para obtener soporte o contribuir a la MongoDB Community, consulte la MongoDB Developer Community.