Spring Boot集成Spring Batch运行时CSV数据重复写入数据库问题
解决Spring Batch重复导入CSV数据的问题
问题根源
你当前使用RunIdIncrementer作为作业增量器,每次启动应用时都会生成新的run.id参数,Spring Batch会将其判定为新的作业实例,从而重复执行整个导入流程,导致CSV数据持续追加到数据库。以下是几种可行的解决方案:
方案1:阻止作业重复自动执行
修改作业配置,移除自动生成新作业实例的增量器,同时配置作业不允许重复执行:
@Bean public Job importUserJob(JobCompletionNotificationListener listener) { return jobBuilderFactory.get("importUserJob") .preventRestart() // 标记作业完成后不允许重启 .listener(listener) .flow(step1()) .end() .build(); }
如果需要保留手动触发作业的能力,但避免应用启动时自动重复执行,可以添加作业执行状态检查:
@Bean public Job importUserJob(JobCompletionNotificationListener listener, JobExplorer jobExplorer) { Job job = jobBuilderFactory.get("importUserJob") .listener(listener) .flow(step1()) .end() .build(); // 检查作业是否已完成过,避免启动时重复执行 Set<JobInstance> jobInstances = jobExplorer.getJobInstances("importUserJob", 0, 1); if (!jobInstances.isEmpty()) { JobInstance jobInstance = jobInstances.iterator().next(); JobExecution execution = jobExplorer.getJobExecution(jobInstance.getJobInstanceId()); if (execution != null && execution.getStatus() == BatchStatus.COMPLETED) { return job; } } return job; }
方案2:数据库层面添加唯一约束
在Covid对应的数据库表中,给唯一标识字段(比如id)添加唯一索引,从根源上阻止重复数据插入。同时配置Spring Batch跳过唯一约束冲突的异常:
1. 数据库表添加唯一索引
ALTER TABLE covid ADD UNIQUE KEY uk_covid_id (id);
2. 修改Step配置跳过异常
@Bean public Step step1(ItemReader<Covid> reader, ItemProcessor<Covid, Covid> processor, ItemWriter<Covid> writer) { return stepBuilderFactory.get("step1") .<Covid, Covid>chunk(10) .reader(reader) .processor(processor) .writer(writer) .faultTolerant() .skip(SQLIntegrityConstraintViolationException.class) // 跳过唯一约束冲突异常 .skipLimit(100) // 根据实际数据量设置允许跳过的次数 .build(); }
方案3:在ItemProcessor中过滤已存在数据
编写自定义处理器,在数据写入前检查数据库是否已存在该记录,存在则跳过:
1. 实现去重处理器
@Component public class DuplicateCovidProcessor implements ItemProcessor<Covid, Covid> { @Autowired private CovidRepository covidRepository; // 注入对应的数据访问层Bean @Override public Covid process(Covid item) throws Exception { // 根据唯一标识检查数据库中是否已存在 if (covidRepository.existsById(item.getId())) { return null; // 返回null表示跳过当前记录 } return item; } }
2. 修改Step配置添加处理器
@Bean public Step step1(ItemReader<Covid> reader, DuplicateCovidProcessor processor, ItemWriter<Covid> writer) { return stepBuilderFactory.get("step1") .<Covid, Covid>chunk(10) .reader(reader) .processor(processor) // 加入去重处理器 .writer(writer) .build(); }
额外配置优化
你的application.properties中spring.batch.jdbc.initialize-schema=always会在每次启动时重新初始化Batch元数据表,可能导致作业执行记录丢失,建议修改为:
# 仅在嵌入式数据库时初始化,生产环境建议手动创建元数据表后设置为never spring.batch.jdbc.initialize-schema=embedded
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

