You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Batch 4.3.x升级至5.0.x(MongoDB作业仓库)问题咨询

Spring Boot 3.0(Spring Batch 5.0)迁移问题:批量配置Job/Step避免逐个传入组件

迁移背景与现有配置

我正在将基于MongoDB作业仓库的Spring Boot 2.7.x(对应Spring Batch 4.3.x)迁移至Spring Boot 3.0.x(对应Spring Batch 5.0.x)。原代码实现的BatchConfigurer接口已被移除,调整后的配置类如下:

@Configuration
public class MainBatchConfigurer  {

    @Autowired
    private ExecutionContextDao mongoExecutionContextDao;

    @Autowired
    private JobExecutionDao mongoJobExecutionDao;

    @Autowired
    private JobInstanceDao mongoJobInstanceDao;

    @Autowired
    private StepExecutionDao mongoStepExecutionDao;

    @Bean
    public JobRepository jobRepository() {
        return new SimpleJobRepository(mongoJobInstanceDao, mongoJobExecutionDao, mongoStepExecutionDao, mongoExecutionContextDao);
    }

    @Bean
    public PlatformTransactionManager getTransactionManager() {
        return new ResourcelessTransactionManager();
    }


    public TaskExecutorJobLauncher getJobLauncher() throws Exception {
        TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
        jobLauncher.setJobRepository(jobRepository());
        jobLauncher.afterPropertiesSet();
        return jobLauncher;
    }

    @Bean
    public JobExplorer getJobExplorer() {
        return new SimpleJobExplorer(mongoJobInstanceDao, mongoJobExecutionDao, mongoStepExecutionDao, mongoExecutionContextDao);
    }

}

原作业调用方式:

SimpleJobLauncher jobLauncher = batchConfigurer.getJobLauncher();
JobExecution jobExecution = jobLauncher.run(xxx, jobParameters);

核心问题

Spring Batch 5.0.x中创建Step和Job时需要传入JobRepository和TransactionManager,但我有大量作业和步骤,不想逐个手动设置这些组件(已在TaskExecutorJobLauncher中配置)。当前作业和步骤定义示例如下:

@Bean
public Step departmentMigrationStep() throws UnexpectedInputException, ParseException {
    return stepBuilderFactory.get("departmentMigratioStep")
            .<departments, departments>chunk(10000)
            .reader(departmentPeekingreader())
            .processor(departmentprocessor())
            .writer(departmentwriter)
            .listener(genericItemReadListener)
            .listener(genericSkipListener)
            .listener(genericStepExecutionListener)
            .listener(genericChunkListener)
            .build();
}

@Bean
public Step departmentValidationStep() throws UnexpectedInputException, ParseException {
    return stepBuilderFactory.get("departmentValidationStep")
            .<xxx, yyy>chunk(10000)
            .reader(departmentPeekingreader)
            .processor(departmentValidationProcessor())
            .writer(departmentValidationWriter)
            .listener(genericChunkListener)
            .build();
}


@Bean
public Step deparmentMasterStep() throws UnexpectedInputException, ParseException {
    return stepBuilderFactory.get("deparmentMasterStep")
            .partitioner("workerStep",departmentPartitioner())
            .step(departmentMigrationStep())
            .taskExecutor(departmentExecutor())
            .gridSize(20)
            .build();

}

@Bean
public Step departmentValidationMasterStep() throws UnexpectedInputException, ParseException{

    return stepBuilderFactory.get("departmentValidationMasterStep")
            .partitioner("workerStep",departmentPartitioner())
            .step(departmentValidationStep())
            .taskExecutor(departmentExecutor())
            .gridSize(20)
            .build();

}


@Primary
@Bean
public Job processDepartmentMigration() {
    return jobBuilderFactory.get("processDepartmentMigration")
            .incrementer(new RunIdIncrementer()).listener(departmentJobListener())
            .start(deparmentMasterStep())
            .build();
}

@Bean
public Job processdepartmentValidation() {
    return jobBuilderFactory.get("processdepartmentValidation")
            .incrementer(new RunIdIncrementer()).listener(departmentJobListener())
            .start(departmentValidationMasterStep())
            .build();
}

解决方案

1. 配置全局默认的JobBuilderFactory和StepBuilderFactory

在Spring Batch 5中,JobBuilderFactory和StepBuilderFactory可以通过构造函数注入全局的JobRepository和PlatformTransactionManager,这样所有通过工厂创建的Job和Step都会自动复用这些组件,无需逐个设置。

修改你的MainBatchConfigurer,添加以下Bean定义:

@Bean
public JobBuilderFactory jobBuilderFactory(JobRepository jobRepository) {
    return new JobBuilderFactory(jobRepository);
}

@Bean
public StepBuilderFactory stepBuilderFactory(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
    return new StepBuilderFactory(jobRepository, transactionManager);
}

2. 修正JobLauncher的Bean定义

原getJobLauncher()方法未添加@Bean注解,导致Spring无法管理其生命周期,修改后让Spring自动注入:

@Bean
public TaskExecutorJobLauncher getJobLauncher() throws Exception {
    TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
    jobLauncher.setJobRepository(jobRepository());
    jobLauncher.afterPropertiesSet();
    return jobLauncher;
}

对应的作业调用方式改为注入JobLauncher:

@Autowired
private JobLauncher jobLauncher;

// 调用执行作业
JobExecution jobExecution = jobLauncher.run(xxx, jobParameters);

额外注意事项

  • 确保你的MongoDB相关DAO类(mongoExecutionContextDao等)已适配Spring Batch 5的接口规范,避免版本兼容性问题。
  • ResourcelessTransactionManager适用于不需要事务控制的场景,若你的作业涉及需要事务的操作,需替换为对应场景的事务管理器(如JDBC场景用DataSourceTransactionManager),MongoDB场景下使用ResourcelessTransactionManager是合适的。

内容的提问来源于stack exchange,提问作者Giri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 14:36:07