Spring batch 使用@StepScope时,Spring批处理重新启动功能不起作用
我想使用Spring批处理(v3.0.9)重启功能,以便在Spring batch 使用@StepScope时,Spring批处理重新启动功能不起作用,spring-batch,Spring Batch,我想使用Spring批处理(v3.0.9)重启功能,以便在JobInstance重启时,流程步骤从上一个失败的区块点向前读取。只要我不对我的myBatisPagingItemReaderbean方法使用@StepScope注释,我的重启就可以正常工作。 我使用的是@StepScope,这样我就可以在myBatisPagingItemReaderbean方法@Value(“{JobParameters['run-date']}”)中进行后期绑定来获取JobParameters 如果我在myBati
JobInstance
重启时,流程步骤从上一个失败的区块点向前读取。只要我不对我的myBatisPagingItemReader
bean方法使用@StepScope
注释,我的重启就可以正常工作。我使用的是
@StepScope
,这样我就可以在myBatisPagingItemReader
bean方法@Value(“{JobParameters['run-date']}”)中进行后期绑定来获取JobParameters
如果我在myBatisPagingItemReader()
bean方法上使用@StepScope
注释,则重新启动不会工作,因为它会创建新实例(scope=step,name=scopedTarget.myBatisPagingItemReader)。
如果使用stepscope,myBatisPagingItemReader是否可以设置上次重新启动工作失败时的read.count
我已经用下面的例子解释了这个问题
@Configuration
@EnableBatchProcessing
public class BatchConfig {
@Bean
public Step step1(StepBuilderFactory stepBuilderFactory,
ItemReader<Model> myBatisPagingItemReader,
ItemProcessor<Model, Model> itemProcessor,
ItemWriter<Model> itemWriter) {
return stepBuilderFactory.get("data-load")
.<Model, Model>chunk(10)
.reader(myBatisPagingItemReader)
.processor(itemProcessor)
.writer(itemWriter)
.listener(itemReadListener())
.listener(new JobParameterExecutionContextCopyListener())
.build();
}
@Bean
public Job job(JobBuilderFactory jobBuilderFactory, @Qualifier("step1")
Step step1) {
return jobBuilderFactory.get("load-job")
.incrementer(new RunIdIncrementer())
.start(step1)
.listener(jobExecutionListener())
.build();
}
@Bean
@StepScope
public ItemReader<Model> myBatisPagingItemReader(
SqlSessionFactory sqlSessionFactory,
@Value("#{JobParameters['run-date']}") String runDate)
{
MyBatisPagingItemReader<Model> reader = new
MyBatisPagingItemReader<>();
Map<String, Object> parameterValues = new HashMap<>();
parameterValues.put("runDate", runDate);
reader.setSqlSessionFactory(sqlSessionFactory);
reader.setParameterValues(parameterValues);
reader.setQueryId("query");
return reader;
}
}
@配置
@启用批处理
公共类BatchConfig{
@豆子
公共步骤step1(StepBuilderFactory StepBuilderFactory,
ItemReader myBatisPagingItemReader,
ItemProcessor ItemProcessor,
项目编写器(项目编写器){
返回stepBuilderFactory.get(“数据加载”)
.chunk(10)
.reader(myBatisPagingItemReader)
.processor(项目处理器)
.writer(项目编写器)
.listener(itemReadListener())
.listener(新作业参数ExecutionContextCopyListener())
.build();
}
@豆子
公共作业作业(JobBuilderFactory JobBuilderFactory,@Qualifier(“step1”)
步骤1){
返回jobBuilderFactory.get(“加载作业”)
.incrementer(新的RunIdIncrementer())
.开始(步骤1)
.listener(jobExecutionListener())
.build();
}
@豆子
@步进镜
公共项目阅读器myBatisPagingItemReader(
SqlSessionFactory SqlSessionFactory,
@值(“#{JobParameters['run-date']}”)字符串runDate)
{
MyBatisPagingItemReader=新建
MyBatisPagingItemReader();
Map parameterValues=newhashmap();
parameterValues.put(“runDate”,runDate);
reader.setSqlSessionFactory(sqlSessionFactory);
reader.setParameterValues(parameterValues);
reader.setQueryId(“查询”);
返回读取器;
}
}
重新启动示例当我使用@Stepscope
注释到myBatisPagingItemReader()
时,读取器正在获取5条记录,并且我将块大小(提交间隔)设置为3
作业实例-01-作业参数-01/02/2019。
chunk-1:
-过程记录-1
-过程记录-2
-过程记录-3
writer-写入所有3条记录
chunk-1提交成功
区块2:
过程记录-4
流程记录-5-抛出和异常
作业完成并设置为“失败”状态
现在使用相同的作业参数重新启动作业。
作业实例-01-作业参数-01/02/2019。
chunk-1:
过程记录-1
过程记录-2
过程记录-3
writer-写入所有3条记录
chunk-1提交成功
区块2:
过程记录-4
流程记录-5-抛出和异常
作业完成并设置为“失败”状态
myBatisPagingItemReader()
bean方法上的@StepScope
注释创建了一个新实例,请参见下面的日志消息。
在scope=step,name=scopedTarget.myBatisPagingItemReader中创建对象
在scope=step,name=scopedTarget.myBatisPagingItemReader中注册了销毁回调
因为它是一个新实例,所以它从start开始启动流程,而不是从chunk-2开始
如果我不使用@Stepscope
,则当重新启动的作业步骤设置为-MyBatisPagingItemReader.read.count=3时,它将从chunk-2重新启动 这里的问题是,您返回的是ItemReader
,而不是完全限定的类(MyBatisPagingItemReader
),或者至少是itemreamReader
。当您使用SpringBatch的StepScope时,我们会创建一个代理以允许延迟初始化。代理基于方法的返回类型(ItemReader
)。您遇到的问题是,由于代理是ItemReader
,Spring批处理不知道您的bean也实现了ItemStream
,正是该接口实现了可重启性。默认情况下,springbatch将自动为您注册类型为ItemStream
的所有bean(您也可以自己显式注册bean,但通常不需要)
为了解决您的问题,以下方法应该有效(注意退货类型的变化):
@Bean
@步进镜
公共MyBatisPagingItemReader MyBatisPagingItemReader(
SqlSessionFactory SqlSessionFactory,
@值(“#{JobParameters['run-date']}”)字符串runDate){
MyBatisPagingItemReader读取器=
新的MyBatisPagingItemReader();
Map parameterValues=newhashmap();
parameterValues.put(“runDate”,runDate);
reader.setSqlSessionFactory(sqlSessionFactory);
reader.setParameterValues(parameterValues);
reader.setQueryId(“查询”);
返回读取器;
}
这就是为什么我建议在可能的情况下,当使用@Bean
带注释的方法时,应该返回尽可能具体的类型,以允许Spring尽可能多地提供帮助。当使用StepScope
并且作业第一次尝试失败时,在重新启动之前,能否共享步骤执行上下文中的read.count
值?如何重新启动作业?即使存在读卡器的新实例,此实例也将使用上次(失败)步骤执行中的read.count
进行初始化,并从此处继续。我看不出使用或不使用StepScope会如何影响可重启性
@Bean
@StepScope
public MyBatisPagingItemReader<Model> myBatisPagingItemReader(
SqlSessionFactory sqlSessionFactory,
@Value("#{JobParameters['run-date']}") String runDate) {
MyBatisPagingItemReader<Model> reader =
new MyBatisPagingItemReader<>();
Map<String, Object> parameterValues = new HashMap<>();
parameterValues.put("runDate", runDate);
reader.setSqlSessionFactory(sqlSessionFactory);
reader.setParameterValues(parameterValues);
reader.setQueryId("query");
return reader;
}