我有一个春季批处理分区工作。基本上,这样做是将处理db中的数据行并提供一些输出。但是我得到的日志无法正确对其进行分区。记录表已处理并显示结果标志,当完成处理时,会将结果标志设置为Y,已处理标志仍为N。由于itemreader正在对已处理标志进行选择,所以我不想在处理过程中更改它。这就是为什么我添加结果标志。完成该分区作业后,将有另一个作业设置为要处理的结果。
@Bean
@StepScope
public dbItemReader(@Value("${executionContext[from]}") Long from, @Value("${executionContext[to]}") Long to,
@Value("${executionContext[partitionId]}") Long partitionId){
RepositoryItemReader<Record> itemReader = new RepositoryItemReader<>();
itemReader.setRepository(dataRepo);
//Select record from Record record where processed=:processed and rownum >=:from and rownum < :to;
itemReader.setMethod("findByProcessedBetweenFromAndTo");
List<Object> params = new ArrayList<>();
params.put("N");
params.put(from);
params.put(to);
itemReader.setArguments(params);
return itemReader;
}
@Bean
public dbItemProcessor(){
RecordItemProcessor<Record> itemProcessor = new RecordItemProcessor<>();
return itemProcessor;
}
@Bean
public writer(){
RepositoryItemWriter writer = new RepositoryItemWriter();
writer.setRepository(dataRepo);
writer.setMethod("save");
return writer;
}
@Bean
public Partition partitioner() {
Partition p = new Partition();
p.setTotalCount(dataRepo.count());
return p;
}
//Partition class just @override method
@Override
public Map<String, ExecutionContext> partition(int gridSize) {
Map<String, ExecutionContext> map = new HashMap<>(gridSize);
int start = 1;
int range = this.totalCount / gridSize + 1;
for (int i=0; to gridSize) {
ExecutionContext context = new ExecutionContext();
context.putString("from", start);
context.putString("to", start + range);
context.putString("partitionId", i);
start += range;
map.put("Partition"+ i, context);
}
return map;
}
@Bean
public Step slaveStep()
throws UnexpectedInputException, MalformedURLException, ParseException {
return steps.get("slaveStep").<Record, Record>chunk(1)
.reader(dbItemReader(null,null,null))
.processor(dbItemProcessor())
.writer(itemWriter())
.build();
}
@Bean
public Step partitionStep()
throws UnexpectedInputException, MalformedURLException, ParseException {
return steps.get("partitionStep")
.partitioner("slaveStep", partitioner())
.step(slaveStep())
.taskExecutor(taskExecutor())
.gridSize(10)
.build();
}
//omit job setup
上面是示例代码,整个想法是我将整个db划分为10个分区,比如totalCount为100,每个分区将读取1-10、10-20,依此类推。因此最后将处理所有100个并将Result设置为Y。但是,当该分区作业完成时,仍有记录具有result = N,这意味着跳过了某些记录。
当我检查日志时,itemprocessor正在以某种方式处理重复记录
Thread 10 - Info: Processing record: 2
Thread 4 - Info: Processing record: 40
Thread 3 - Info: Processing record: 20
so on
//after some time, there will be threads reading the same record again
Thread 5 - Info: Processing record: 20 //it suppose process 60-70 for example
我在想,如果将数据划分为10个分区,每个分区都应该有自己的一组数据要处理,并且永远不要接触另一组数据。 对?分区的用途是什么?按钮行是应该处理的所有数据。有多个分区作业,它们可能同时运行。
我不知道自己做错了什么,所以我需要一些帮助。