Visão geral
Neste tutorial, você pode aprender como usar Spring Data MongoDB com o driver Java para executar inserções em massa de alto desempenho em um aplicativo Spring Boot.
Spring Data MongoDB
O Spring Data MongoDB é o mapeador de documento de objeto (ODM) oficial da Spring Data para o MongoDB. Ele permite a interação com o MongoDB usando objetos Java antigos simples (POJOs) e abstração de repositório. Ele oferece suporte a recursos específicos do MongoDB, como queries dinâmicas, indexação e mapeamento de documentos aninhados, ao mesmo tempo em que reduz o código boilerplate, como chamadas manuais de find() e update().
Bota de primavera
O Spring Boot é um framework criado sobre o Spring Framework. Ele adiciona recursos de configuração automática, padrões e recursos prontos para produção para simplificar a criação de aplicativos Java baseados em Spring, incluindo a integração com o Spring Data MongoDB. Para obter mais informações, consulte a documentação do Spring Boot.
Injeção de dependência
A injeção de dependência (DI) é um princípio fundamental do Spring Framework. Ele permite que o contêiner Spring crie e gerencie objetos, chamados feições, e então os injete em outros feições que os utilizam. Isso é diferente do desenvolvimento típico orientado a objetos, em que as classes são responsáveis por inicializar e construir os objetos que usam.
Para obter mais informações sobre injeção de dependência, consulte a página Injeção de dependência da documentação do Spring Framework.
Interface de BulkOperations de dados da primavera
BulkOperations é uma interface Spring Data MongoDB que contém uma lista de operações de gravação que podem ser aplicadas ao seu banco de dados. Ele pode lidar com qualquer combinação das seguintes operações, que são mapeadas para operações semelhantes do driver Java do MongoDB :
insertupdateOneupdateManyreplaceOnedeleteOnedeleteManyupsert
Um BulkOperation pode ser ordenado ou não ordenado. As operações em massa ordenadas executam operações sequencialmente e, se um erro for detectado, retorne com um código de erro. Operações não ordenadas são executadas em paralelo, o que significa que elas normalmente são mais rápidas. No entanto, você deve verificar manualmente se houve erros durante as operações.
Para obter mais informações sobre operações em massa, consulte os seguintes recursos:
BulkOperations na documentação da API do Spring Framework
Operações de gravação em massa neste guia
Operações de gravação em massa no manual do MongoDB Server
Tutorial
Você pode encontrar o aplicativo de amostra concluído para este tutorial no repositório GitHub do projeto de amostra SpringDataBulkInsert.
Observação
Importações não especificadas
Esta página não inclui as declarações de importação necessárias para os arquivos no tutorial. Consulte o repositório GitHub para arquivos completos.
Pré-requisitos
Certifique-se de ter os seguintes componentes instalados e configurados antes de iniciar este tutorial:
Adicionar dependências
Certifique-se de usar uma versão do Spring Data MongoDB compatível com o driver Java do MongoDB e as versões Java que você está usando. Para obter especificações de compatibilidade, consulte a página Requisitos da documentação do Spring Data MongoDB, e a página Compatibilidade deste guia.
Observação
Se você usou o Spring Initializr ou um clone do projeto de amostra Spring Boot para criar seu projeto, a compatibilidade de versão já foi contabilizada e o componente spring-boot-starter-data-mongodb já será incluído no seu arquivo pom.xml.
Adicione as seguintes dependências ao seu arquivo 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>
A dependência datafaker é usada para gerar uma grande quantidade de objetos Product para usar na operação de gravar em massa.
Configure seu MongoClient
A classe MongoConfig contém a configuração do objeto MongoClient que permitirá que o framework Spring Data interaja com o MongoDB Server e define outras opções de configuração. Para obter mais informações sobre as opções de configuração, consulte a página Especificar opções de conexão deste guia.
Este aplicativo usa anotações @Configuration para classes, anotações @Bean para métodos e anotações @Value para conversão de parâmetros. Essas anotações permitem que o contêiner Spring Inversion of Control (IoC) gerencie objetos. Para obter uma explicação detalhada dessas anotações, consulte as seguintes seções do guia do framework Spring Data:
@Configuratione anotações@Bean: configuração de contêiner baseada em Java@Valueanotações: uso de @Value
Crie um arquivo MongoConfig.java e adicione as seguintes classes de configuração e modelo para configurar sua conexão 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); } }
Observação
API versus interface
Essa implementação usa a API MongoTemplate, em vez de estender uma interface de repositório de dados da Spring, como MongoRepository, para permitir o controle refinado sobre operações em massa.
Defina os valores de sua string de conexão (mongodb.uri), nome do banco de dados (mongodb.database) e contagem de operações em massa (documentCount) no seu arquivo application.properties:
mongodb.database=bulk mongodb.uri=<connection string> documentCount=25000
Este tutorial usa um banco de dados chamado bulk e cria 25,000 documentos para salvar. Substitua o espaço reservado do <connection
string> pela string de conexão para sua implantação do Atlas. Para obter mais informações, consulte a seção Criar uma string de conexão deste guia.
Mapear seu objeto para um documento
O mapeamento de uma classe para uma coleção permite que o contêiner Spring IoC armazene objetos como documentos MongoDB. Você pode usar a anotação @Document para especificar para qual coleção uma classe mapeia. Para obter mais informações sobre o mapeamento de objetos para documentos do MongoDB, consulte a seção Visão geral da anotação de mapeamento da documentação do Spring Data MongoDB.
A anotação @Id no código a seguir indica que o campo de objeto id mapeia para o campo de documento _id, que é usado como identificador exclusivo em documentos do MongoDB. Você pode escolher qualquer campo de qualquer tipo, exceto arrays, para ser o identificador exclusivo. Para obter mais informações, consulte a Como o campo _id é tratado na camada de mapeamento da documentação do Spring Data MongoDB.
Use o código a seguir para criar um arquivo Product.java para definir sua classe Product e mapeá-la para sua coleção 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 }
A classe Product inclui um método estático que gera uma array de objetos Product. Você também pode definir getters e setters para os campos.
Defina um repositório para armazenar seus produtos
O objeto ProductRepository gerenciará uma coleção de Product objetos. Seu objeto ProductRepository deve ser injetado com o bean MongoTemplate gerado na classe MongoConfig . Ao usar a anotação @Autowired com um construtor que inclui mongoTemplate como argumento, o contêiner Spring usa a injeção de construtor para injetar uma dependência mongoTemplate . Para obter mais informações sobre injeção de construtor, consulte a seção Injeção de dependência baseada em construtor da documentação do Spring Framework.
Use o código a seguir para criar o arquivo ProductRepository.java e definir sua classe ProductRepository para gerenciar uma coleção 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(); } }
O método bulkInsertProducts() utiliza inserções em massa não ordenadas, que podem melhorar o desempenho por não oferecer garantias quanto à ordem das operações.
Realizar uma operação em massa
A classe do aplicativo principal aciona o ProductRepository para gerar o número especificado de objetos Product e salvá-los em seu banco de dados MongoDB. Ele utiliza a anotação @Autowired para injetar um ProductRepository e implementa o registro.
Adicione o seguinte código à sua classe principal para executar seu aplicativo:
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); } }
Conclusão
Spring Data MongoDB fornece uma abstração de alto nível para trabalhar com MongoDB. Ele pode simplificar a arquitetura do aplicativo ao oferecer suporte à injeção automática de dependências, o que elimina a necessidade de configuração manual do cliente e tratamento complexo de querys. Ao reduzir o código boilerplate e oferecer suporte ao acesso aos dados orientado a objetos, ele pode simplificar o acesso aos dados e promover uma clara separação de preocupações.
Mais recursos
Para obter mais informações sobre os frameworks Spring e Spring Data MongoDB, consulte os seguintes recursos:
Para obter suporte ou contribuir para a MongoDB Community, consulte a Comunidade de desenvolvedores MongoDB.