我有弹簧批量应用程序,它读取和写入同一个表。我使用分页来读取表中的项目,因为我的数据量非常高。当我将块大小设置为大于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;
}
答案 0 :(得分:2)
请勿使用分页阅读器。问题是,这个阅读器为每个块执行一个新的查询。因此,如果在写入期间在同一个表中添加项目或更改项目,则查询将不会产生相同的结果。
在分页阅读器的代码中潜入一点,这在那里显而易见。
如果您修改了正在阅读的同一个表,那么您必须确保在整个步骤的处理过程中结果集不会改变,否则,您的结果可能无法预测,很可能不是您想要的
尝试使用jdbccursoritemreader。这个在步骤开始时创建查询,因此,结果集在开头定义,在处理步骤时不会改变。
<强> Editet 强>
根据您的代码来配置您添加的阅读器,我假设了以下几点:
这不是标准的弹簧式项目阅读器
您正在使用名为“findAllByStatusCode”的方法。我假设,这是在写作期间更新的状态字段
您的Reader-Class被命名为“NonSortingRepositoryItemReader”,因此,我假设您的结果列表中没有保证订购
如果3是正确的,那么这很可能就是问题所在。如果不保证元素的顺序,那么使用分页阅读器绝对不行。 每个页面都执行它自己的选择,然后移动到指向结果中适当位置的指针。
例如,如果你有一个5的页面大小,第一个调用将返回其select的元素1-5,第二个调用将返回其select的元素6-10。但由于订单无法保证,第一次呼叫中位置1的元素可能位于第二次呼叫中的位置6,因此被处理2,而第一次呼叫中的元素6可能位于第二次呼叫中的位置2,因此从未被处理过。