【问题标题】:Duplicate Spring Batch Job Instance重复 Spring Batch 作业实例
【发布时间】:2013-11-05 00:49:51
【问题描述】:

我有一个小型 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() });
    }
}

网络服务类

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

【问题讨论】:

    标签: java spring spring-batch spring-boot


    【解决方案1】:

    发现问题。当使用 Spring Boot 中的 @EnableAutoConfiguration 注释时,它将调用 org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration 类,该类将从“schema-mysql.sql”文件中初始化数据库。

    schema-mysql.sql 文件内有一些代码用于重置批处理元表的序列 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 表。

    要为其他组件排除或自定义 Spring 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

    【讨论】:

    • 当我这样做时,批处理作业永远不会运行。
    【解决方案2】:

    我也遇到过类似的问题,也尝试过上面的解决方案,但是没有用。所以我用一种解决方法修复了它。

    BATCH_JOB_INSTANCE 表创建 spring 批处理元数据模式时,为 JOB_INSTANCE_ID 列添加 AUTO_INCREMENT,它将解决您的问题。 p>

    【讨论】:

      猜你喜欢
      • 2015-03-05
      • 2012-06-12
      • 1970-01-01
      • 1970-01-01
      • 2019-06-09
      • 2014-12-24
      • 1970-01-01
      • 1970-01-01
      • 2015-08-27
      相关资源
      最近更新 更多