Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring batch 使用@StepScope时,Spring批处理重新启动功能不起作用_Spring Batch - Fatal编程技术网

Spring batch 使用@StepScope时,Spring批处理重新启动功能不起作用

Spring batch 使用@StepScope时,Spring批处理重新启动功能不起作用,spring-batch,Spring Batch,我想使用Spring批处理(v3.0.9)重启功能,以便在JobInstance重启时,流程步骤从上一个失败的区块点向前读取。只要我不对我的myBatisPagingItemReaderbean方法使用@StepScope注释,我的重启就可以正常工作。 我使用的是@StepScope,这样我就可以在myBatisPagingItemReaderbean方法@Value(“{JobParameters['run-date']}”)中进行后期绑定来获取JobParameters 如果我在myBati

我想使用Spring批处理(v3.0.9)重启功能,以便在
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;
   }