重复的Spring批处理作业示例

yc0p9oo0  于 2023-03-23  发布在  Spring
关注(0)|答案(3)|浏览(170)

我有一个小的Spring Batch应用程序示例,第一次启动时可以正常工作,但每当我关闭应用程序并重新启动jar时,我总是得到这个错误:

Caused by: org.springframework.dao.DuplicateKeyException: PreparedStatementCallback; SQL [INSERT into BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) values (?, ?, ?, ?)]; Duplicate entry '1' for key 1; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 1

我不确定我是否把作业增量器设置错了。但是就像我说的,我可以启动它,然后使用web服务url /jobLauncher.html来调用批处理进程任意次数。只有在我关闭应用程序并重新启动它之后,我才得到这个错误。它想使用id 1作为作业执行表,但是id 1在以前的运行中已经存在了。
主类

@EnableAutoConfiguration
@ComponentScan
public class Application {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, new String[]{ "date=" + System.currentTimeMillis() });
    }
}

Web服务类

@Controller
public class JobLauncherController {

    @Autowired
    JobLauncher jobLauncher;

    @Autowired
    Job job;

    @RequestMapping("/jobLauncher.html")
    @ResponseBody
    public String handle() throws Exception{
        jobLauncher.run(job, new JobParametersBuilder().addString("date", System.currentTimeMillis() + "").toJobParameters());
        return "Started the batch...";
    }
}

Spring Batch类

@Configuration
@EnableBatchProcessing
public class SampleBatchApplication {

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    @Bean
    protected Tasklet tasklet() {
        return new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution contribution,
                                        ChunkContext context) {
                return RepeatStatus.FINISHED;
            }
        };
    }

    @Bean
    public Job job() throws Exception {
        return this.jobs.get("job")
                   .incrementer(new RunIdIncrementer())
                   .flow(this.step1())
                   .end()
                   .build();
    }

    @Bean
    protected Step step1() throws Exception {
        return this.steps.get("step1").tasklet(this.tasklet()).build();
    }

    @Bean
    public DataSource dataSource() {

        BasicDataSource ds = new BasicDataSource();

        try {
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setUsername("test");
            ds.setPassword("test");
            ds.setUrl("jdbc:mysql://127.0.0.1:3306/spring-batch");

        } catch (Exception e) {
            e.printStackTrace();
        }
        return ds;
    }
}
x9ybnkn6

x9ybnkn61#

发现问题。当从Sping Boot 使用@EnableAutoConfiguration注解时,它将调用org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration类,该类将从'schema-mysql.sql'文件初始化数据库。
schema-mysql.sql文件中有一些代码,用于重置批处理 meta表的序列ID,这就是为什么我得到一个重复的键错误:

INSERT INTO BATCH_STEP_EXECUTION_SEQ values(0);
INSERT INTO BATCH_JOB_EXECUTION_SEQ values(0);
INSERT INTO BATCH_JOB_SEQ values(0);

修复方法是单独构建Spring Batch表,然后将@EnableAutoConfiguration注解更改为:

@EnableAutoConfiguration(exclude={BatchAutoConfiguration.class})

这样,当应用程序启动时,它就不会尝试初始化Spring Batch表。
要排除或自定义Sping Boot 的其他组件的自动配置,您可以在这里找到一些文档:http://projects.spring.io/spring-boot/docs/spring-boot-autoconfigure/README.html
BatchAutoConfiguration代码:https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java

62lalag4

62lalag42#

我也遇到过类似的问题,也尝试过上面的解决方案,但是没有效果。所以我用了一个解决方案。
在为表BATCH_JOB_INSTANCE创建spring batch元数据模式时,为列JOB_INSTANCE_ID添加AUTO_INCREMENT,它将解决您的问题。

vm0i2vca

vm0i2vca3#

使用以下查询在 *seq表中插入初始值,也可以使用0代替10。
INSERT INTO BATCH_STEP_EXECUTION_SEQ(ID,UNIQUE_KEY)select * from(select 10 as ID,'0' as UNIQUE_KEY)as tmp where not exists(select * from BATCH_STEP_EXECUTION_SEQ);
INSERT INTO BATCH_JOB_SEQ(ID,UNIQUE_KEY)select * from(select 10 as ID,'0' as UNIQUE_KEY)as tmp where not exists(select * from BATCH_JOB_SEQ);
INSERT INTO BATCH_JOB_EXECUTION_SEQ(ID,UNIQUE_KEY)select * from(select 10 as ID,'0' as UNIQUE_KEY)as tmp where not exists(select * from BATCH_JOB_EXECUTION_SEQ);

相关问题