【问题标题】:Spring batch Read/write in the same tableSpring批处理在同一张表中读/写
【发布时间】:2017-02-18 16:57:20
【问题描述】:

我有 spring 批处理应用程序,它可以读取和写入同一个表。由于我的数据量很大,所以我使用分页来读取表格中的项目。当我将块大小设置为大于 1 时,我的分页号会错误地更新,因此无法从表中读取某些项目。 有什么想法吗?

@Bean
      public Step fooStep1() {
        return stepBuilderFactory.get("step1")
            .<foo, foo>chunk(chunkSize)
            .reader(fooTableReader())
            .writer(fooTableWriter())
            .listener(fooStepListener())
            .listener(chunkListener())
            .build();
      }

读者

 @Bean
 @StepScope
 public ItemReader<foo> fooBatchReader(){
    NonSortingRepositoryItemReader<foo> reader = new NonSortingRepositoryItemReader<>();
    reader.setRepository(service.getRepository());
    reader.setPageSize(chunkSize);
    reader.setMethodName("findAllByStatusCode");
    List<Object> arguments = new ArrayList<>(); 
    reader.setArguments(arguments);
    arguments.add(statusCode);
    return reader;
}

【问题讨论】:

  • “错误更新”是什么意思?是什么推动了查询?

标签: spring spring-batch


【解决方案1】:

不要使用分页阅读器。问题是,这个阅读器对每个块执行一个新查询。因此,如果您在写入过程中在同一个表中添加项目或更改项目,查询将不会产生相同的结果。

深入了解分页阅读器的代码,那里很明显。

如果您修改您正在读取的同一个表,那么您必须确保您的结果集在整个步骤的处理过程中不会发生变化,否则您的结果可能无法预测并且很可能不是您想要的.

尝试使用 jdbccursoritemreader。这会在您的步骤开始时创建查询,因此,结果集是在开始时定义的,并且在步骤处理期间不会更改。

编辑

根据您添加的阅读器配置代码,我假设有几件事:

  1. 这不是标准的 springbatch 项目阅读器

  2. 您正在使用一种名为“findAllByStatusCode”的方法。我假设,这是在写入过程中更新的状态字段

  3. 您的 Reader-Class 被命名为“NonSortingRepositoryItemReader”,因此,我假设您的结果列表中没有保证排序

如果 3 是正确的,那么这很可能是问题所在。如果不能保证元素的顺序,那么使用分页阅读器肯定行不通。 每个页面都执行它自己的选择,然后将指针移动到结果中的适当位置。

例如,如果您的页面大小为 5,则第一次调用将返回其选择的元素 1-5,第二次调用将返回其选择的元素 6-10。但是由于不能保证顺序,第一次调用中位置 1 的元素可能在第二次调用中位于位置 6,因此被处理 2,而第一次调用中的元素 6 在第二次调用中可能位于位置 2,因此从未被处理过。

【讨论】:

  • 您假设新数据满足查询的要求。情况可能并非如此。事实上,如果您尝试对工作进行分区,您可能想要使用JdbcPagingItemReader。与更改阅读器恕我直言,对于解决您所描述的用例,流程指示器字段是更好的选择。
  • 是的,这是我基于@Deepak 所写的假设。一般来说,我还希望有一个额外的状态字段。然而,这可能并不总是可能的。我还了解到,尤其是从您在stackoverflow.com/questions/20386642/… 的回答中,PagingItemReader 是线程安全的,而 CursorItemReader 不是,这是需要考虑的重要一点。尤其是在使用分区方法或进行并行块处理时。
  • 我不确定是否可以使用 JdbcCursorItemReader,因为我正在使用 JAP 存储库,我需要在阅读器中设置方法名称和存储库。 JdbcCursorItemReader 没有设置方法名称和存储库的方法。因此我正在使用 ItemReader。请参阅上面更新的阅读器代码。
  • 我可以清楚地看到问题所在。您提出的解决方案是什么?
  • 选项 1:使用 jdbcCursorItemReader 并直接访问表。选项 2:使用 HibernateCursorItemReader 并在 HibernateQueryLanguage 中定义查询。选项 3:使用 JpaPagingItemReader 并在 JPQL 中定义查询。选项 4:实现您自己的 SortingRepositoryItemReader 并向您的存储库添加一个方法,该方法以特定顺序返回条目(“findAllByStatusCodeSorted”)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-13
  • 2018-04-12
  • 1970-01-01
  • 2016-06-22
  • 2018-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多