【问题标题】:How to filter items in bulks?如何批量过滤商品?
【发布时间】:2021-08-11 20:10:35
【问题描述】:

我正在用 Spring Batch 实现一个 Job,我的简单场景是:

  1. 从文件中读取项目
  2. 处理每个项目
  3. 将项目块写入数据库

问题是我想过滤掉数据库中已经存在的项目。

我的第一次尝试是在第二步中查询当前项目的数据库,如果已经存在,则从 ItemProcessor 返回 null,以便过滤掉该项目。 这是不必要的慢,因为每个处理的项目都需要一个查询。

所以我的第二次尝试是重写 ItemWriter 中的 doWrite 方法,以对整个块进行单个查询,并只写入查询中没有匹配的项目。 即使性能有了明显的提高,这对我来说也不是很好(这样,Spring Batch 看不到我实际写入数据库的内容,确实来自 StepContext 的写入和过滤计数器的值错误)。

实现这个处理逻辑的正确方法是什么?

【问题讨论】:

    标签: spring spring-batch spring-data-mongodb


    【解决方案1】:

    您似乎调用的skip(如skip the items that are already present in the database)实际上是根据Spring Batch 的术语过滤项目而不是跳过它们。 Spring Batch 中的跳过功能适用于无效项(即在读取、处理或写入时引发异常的项)。

    在您的用例中可以很好地工作的一种常用技术是通过执行“保存或更新”操作使项目编写器具有幂等性。这消除了检查项目是否存在的需要。此外,这在失败的情况下很有用,因为您可以重新运行失败的作业,而无需存储任何进度状态。

    【讨论】:

    • 好吧,这似乎是正确的方法。所以我的第二次尝试就在附近,而不是过滤掉我只需要在 doWrite 方法中实现更新逻辑的项目(我使用的是 MongoItemWriter)。谢谢你的回复
    • 太棒了。由于您使用的是MongoItemWriter,它已经执行了upsert 操作(如果您使用的是Spring Batch 4.3,您将受益于这一改进:github.com/spring-projects/spring-batch/issues/3713)。
    • 我明白了,但可能我需要实现自定义逻辑,因为项目没有设置 id 属性来代替写入。我也想只更新非空值
    【解决方案2】:

    您在 ItemWriter 开始时进行单次选择以查找现有项目的第二种方法是可以的,即使这意味着您不会看到正确的统计数据,这些数据准确地表明有多少行写入数据库以及有多少行因为它们已经存在而被忽略。

    如果您有选择,您可以在与您正在写入的表相同的架构中创建另一个表,然后您可以在 spring 批处理作业的一个阶段将文件中的所有行加载到另一个表中,然后在下一阶段,您从该表中查询并仅选择目标表中不存在的行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多