Spring批处理在同一个表中读/写

时间:2016-10-10 09:39:51

标签: spring spring-batch

我有弹簧批量应用程序,它读取和写入同一个表。我使用分页来读取表中的项目,因为我的数据量非常高。当我将块大小设置为大于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;
}

1 个答案:

答案 0 :(得分:2)

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

在分页阅读器的代码中潜入一点,这在那里显而易见。

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

尝试使用jdbccursoritemreader。这个在步骤开始时创建查询,因此,结果集在开头定义,在处理步骤时不会改变。

<强> Editet

根据您的代码来配置您添加的阅读器,我假设了以下几点:

  1. 这不是标准的弹簧式项目阅读器

  2. 您正在使用名为“findAllByStatusCode”的方法。我假设,这是在写作期间更新的状态字段

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

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

    例如,如果你有一个5的页面大小,第一个调用将返回其select的元素1-5,第二个调用将返回其select的元素6-10。但由于订单无法保证,第一次呼叫中位置1的元素可能位于第二次呼叫中的位置6,因此被处理2,而第一次呼叫中的元素6可能位于第二次呼叫中的位置2,因此从未被处理过。