当前位置:   article > 正文

Spring Boot 实战 MongoDB 实现批量写入_mongo 批量保存

mongo 批量保存

目录

一、概述    

二、开始

三、应用程序类

四、配置类

五、文档类

六、存储库类

七、结论


一、概述    

      Spring数据框架在应用程序中被广泛使用,因为它使访问不同类型的持久性存储变得更容易。这篇文章将展示如何使用SpringDataMongoDB以实现批量插入。
BulkOperations是一个包含要应用于数据库的写入操作列表的接口。它们可以是InsertOne、updateOne updateMany、replaceOne deleteOne deleteMany的任意组合
bulkOperation可以是有序的,也可以是无序的。有序操作将按顺序应用,如果检测到错误,将返回错误代码。无序操作将并行应用,因此可能更快,但应用程序有责任检查操作过程中是否存在错误。有关更多信息,请参阅MongoDB文档的批量写入操作部分。

1、 兼容性表

下面的兼容性表总结了Spring Data版本与MongoDB驱动/数据库版本的关系。

二、开始

POM 文件将指定应用程序将使用的 Spring 数据版本。必须注意使用使用兼容版本的MongoDB Java驱动程序的Spring Data版本。

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-data-mongodb</artifactId>
  5. <version>2.7.2</version>
  6. </dependency>

三、应用程序类

顶级类是一个SpringBootApplication,它实现了CommandLineRunner,如下所示:

  1. @SpringBootApplication
  2. public class SpringDataBulkInsertApplication implements CommandLineRunner {
  3. @Value("${documentCount}")
  4. private int count;
  5. private static final Logger LOG = LoggerFactory
  6. .getLogger(SpringDataBulkInsertApplication.class);
  7. @Autowired
  8. private CustomProductsRepository repository;
  9. public static void main(String[] args) {
  10. SpringApplication.run(SpringDataBulkInsertApplication.class, args);
  11. }
  12. @Override
  13. public void run(String... args) {
  14. repository.bulkInsertProducts(count);
  15. LOG.info("End run");
  16. }
  17. }

现在我们需要编写一些类来实现我们的批量插入应用程序。

四、配置类

我们将实现一个类,该类保存 Spring 数据框架将使用的 MongoClient 对象的配置。
注释 将允许我们检索值以配置对MongoDB环境的访问。
  1. @Configuration
  2. public class MongoConfig {
  3. @Value("${mongodb.uri}")
  4. private String uri;
  5. @Value("${mongodb.database}")
  6. private String databaseName;
  7. @Value("${truststore.path}")
  8. private String trustStorePath;
  9. @Value("${truststore.pwd}")
  10. private String trustStorePwd;
  11. @Value("${mongodb.atlas}")
  12. private boolean atlas;
  13. @Bean
  14. public MongoClient mongo() {
  15. ConnectionString connectionString = new ConnectionString(uri);
  16. MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
  17. .applyConnectionString(connectionString)
  18. .applyToSslSettings(builder -> {
  19. if (!atlas) {
  20. // Use SSLContext if a trustStore has been provided
  21. if (!trustStorePath.isEmpty()) {
  22. SSLFactory sslFactory = SSLFactory.builder()
  23. .withTrustMaterial(Paths.get(trustStorePath), trustStorePwd.toCharArray())
  24. .build();
  25. SSLContext sslContext = sslFactory.getSslContext();
  26. builder.context(sslContext);
  27. builder.invalidHostNameAllowed(true);
  28. }
  29. }
  30. builder.enabled(true);
  31. })
  32. .build();
  33. return MongoClients.create(mongoClientSettings);
  34. }
  35. @Bean
  36. public MongoTemplate mongoTemplate() throws Exception {
  37. return new MongoTemplate(mongo(), databaseName);
  38. }
  39. }

在这个实现中,我们使用一个标志mongodb.atlas来指示这个应用程序将连接到atlas。如果标志为false,则可以使用trustStore创建SSL上下文。这以trustStore.path指向的信任库文件的形式为根证书颁发机构提供证书,在创建时受密码(trustStore.pwd)保护。如果需要,客户端还可以提供密钥库文件,但这并没有实现。
参数mongodb.uri应该包含一个有效的mongodb uri。URI包含客户端连接的主机、用户凭据等。

五、文档类

MongoDB集合与其包含的文档之间的关系是通过由@Document注释修饰的类实现的。此类定义文档的字段,批注定义集合的名称。

  1. @Document("products")
  2. public class Products {
  3. private static final Logger LOG = LoggerFactory
  4. .getLogger(Products.class);
  5. @Id
  6. private String id;
  7. private String name;
  8. private int qty;
  9. private double price;
  10. private Date available;
  11. private Date unavailable;
  12. private String skuId;

需要为每个字段定义设置器和获取器。@Id注释表示我们的默认索引。如果未指定此字段,MongoDB将分配一个唯一的ObjectId值。 

六、批量写入—存储库类

MongoDB驱动支持在一个操作中插入一个文档集合。MongoOperations 接口中的下列方法支持这一功能。

  • insert 方法: 以一个 Collection 作为第一个参数。它们在一次批量写入数据库中插入一个对象的列表。

存储库由两个类实现,一个是接口,另一个是实现接口。存储库类充实了应用程序与数据库的交互。存储库中的一个方法负责批量插入:

  1. @Component
  2. public class CustomProductsRepositoryImpl implements CustomProductsRepository {
  3. private static final Logger LOG = LoggerFactory
  4. .getLogger(CustomProductsRepository.class);
  5. @Autowired
  6. MongoTemplate mongoTemplate;
  7. public int bulkInsertProducts(int count) {
  8. LOG.info("Dropping collection...");
  9. mongoTemplate.dropCollection(Products.class);
  10. LOG.info("Dropped!");
  11. Instant start = Instant.now();
  12. mongoTemplate.setWriteConcern(WriteConcern.W1.withJournal(true));
  13. Products [] productList = Products.RandomProducts(count);
  14. BulkOperations bulkInsertion = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, Products.class);
  15. for (int i=0; i<productList.length; ++i)
  16. bulkInsertion.insert(productList[i]);
  17. BulkWriteResult bulkWriteResult = bulkInsertion.execute();
  18. LOG.info("Bulk insert of "+bulkWriteResult.getInsertedCount()+" documents completed in "+ Duration.between(start, Instant.now()).toMillis() + " milliseconds");
  19. return bulkWriteResult.getInsertedCount();
  20. }
  21. }

七、结论

在这个例子中,我们创建了一个随机的产品列表,然后这些产品被无序地批量插入。我们指定了写问题1,这意味着一旦Primary将操作写入日志,服务器就会确认该操作。
这种写入问题会导致更快的插入,但如果Primary崩溃或发生选举,并且数据尚未复制,则有可能丢失数据。为了避免这种危险,请使用“关注多数”。 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/55993
推荐阅读
相关标签