使用@stepscope时,spring批处理重启功能不起作用

euoag5mw  于 2021-07-23  发布在  Java
关注(0)|答案(1)|浏览(360)

我想使用springbatch(v3.0.9)重启功能 JobInstance 重新启动进程步骤,从最后一个失败的区块点向前读取。只要我不使用 @StepScope 我的注解 myBatisPagingItemReader bean方法。
我用的是 @StepScope 这样我就可以做后期绑定来获得 JobParameters 在我的 myBatisPagingItemReader bean方法 @Value("#{jobParameters['run-date']}")) 如果我使用 @StepScope 上的注解 myBatisPagingItemReader() 重新启动的bean方法在创建新示例(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;
   }
}

使用时重新启动示例 @Stepscope 注解到 myBatisPagingItemReader() ,读取器正在获取5条记录,而我将块大小(提交间隔)设置为3。
作业示例-01-作业参数-01/02/2019。
块-1:
-过程记录-1
-过程记录-2
-过程记录-3
writer-写入所有3条记录
chunk-1提交成功
块-2:
过程记录-4
流程记录-5-抛出和异常
作业完成并设置为“失败”状态
现在使用相同的作业参数重新启动作业。
作业示例-01-作业参数-01/02/2019。
块-1:
过程记录-1
过程记录-2
过程记录-3
writer-写入所有3条记录
chunk-1提交成功
块-2:
过程记录-4
流程记录-5-抛出和异常
作业完成并设置为“失败”状态
这个 @StepScope 上的注解 myBatisPagingItemReader() bean方法创建一个新示例,请参见下面的日志消息。
在scope=step,name=scopedtarget.mybatispagingitemreader中创建对象
在scope=step,name=scopedtarget.mybatispagingitemreader中注册了销毁回调
因为它是新示例,所以它从start开始流程,而不是从chunk-2开始。
如果我不使用 @Stepscope ,当重新启动的作业步骤设置为-mybatispagingitemreader.read.count=3时,它将从chunk-2重新启动。

hts6caw3

hts6caw31#

这里的问题是,你正在返回一个 ItemReader 而不是完全合格的班级( MyBatisPagingItemReader )或者至少 ItemStreamReader . 当您使用springbatch的step作用域时,我们会创建一个代理以允许后期初始化。代理基于方法的返回类型( ItemReader 在你的情况下)。您遇到的问题是,因为代理是 ItemReader ,spring批不知道你的bean也实现了 ItemStream 正是这个接口实现了可重启性。默认情况下,springbatch将自动注册类型为的所有bean ItemStream 对于您(您也可以自己显式注册bean,但通常不需要)。
为了解决您的问题,应该使用以下方法(注意返回类型的更改):

@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;
   }

这就是为什么我建议在可能的情况下 @Bean 对于带注解的方法,应该返回尽可能具体的类型,以允许spring尽可能多地提供帮助。

相关问题