Spring Batch 报 NoUniqueBeanDefinitionException 是因 @EnableBatchProcessing 与 spring-boot-starter-batch 冲突导致双重 JobLauncher 注册;应删除该注解,确保仅引入 starter,自定义时加 @Primary;同时需验证 JobRepository 持久化、JobParameters 唯一性及数据库表名大小写适配。
Spring Batch 依赖没加对,
直接报
Spring Boot 2.5+ 默认不自动配置
,但如果你手动引入了
,又额外加了
,就会触发双重配置冲突——Spring 试图注册两个
实例,而你没指定哪个是 primary。
实操建议:
立即学习
“
Java免费学习笔记(深入)
”;
删掉显式的
(Spring Boot 场景下它多余且有害)
确认只依赖
,别混用
等低层 jar
如果要用自定义
,必须加
注解,例如:
检查是否误把
配置成内存库(如 H2)却没关
,这会导致启动时建表失败并静默降级为内存 JobRepository,后续执行直接抛
数据迁移场景下,
查不出数据但也不报错
常见于源库字段类型和 Java 实体字段不匹配,比如数据库是
,Java 用了
,JDBC 驱动在 ResultSet 取值时悄悄返回 null,而
默认跳过 null 行且不记录日志。
实操建议:
立即学习
“
Java免费学习笔记(深入)
”;
在 reader 的
里加非空校验,例如:
避免用
接数字字段;优先用
或
,再按需转
确认 SQL 中没写死
这类条件,而实际数据状态是
(大小写/空格/编码差异)
开启 JDBC 日志:
,看真实执行的 SQL 和参数绑定
迁移任务跑一半挂了,重启后重复处理或跳过已处理数据
根本原因是
没持久化,或者
每次都传一样的值(比如只用时间戳但没包含毫秒),导致 Spring Batch 认为这是“同一任务”,直接跳过或报
。
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
实操建议:
立即学习
“
Java免费学习笔记(深入)
”;
确保
指向真实数据库,并执行了 Spring Batch 初始化脚本(
或对应数据库版本)
构造
时必须含唯一标识,推荐组合:
不要依赖
—— 它精度只到秒,高并发下极易重复
若要支持断点续跑,reader 必须实现可重启(stateful),比如
比
更稳妥,因它靠分页键推进,不依赖游标位置
从 MySQL 迁到 PostgreSQL,
表名大小写崩了
PostgreSQL 默认把未加引号的表名转小写,而 Spring Batch DDL 脚本里写的是大写表名(如
),导致初始化后实际建出
,但代码里仍按大写查,报
。
实操建议:
立即学习
“
Java免费学习笔记(深入)
”;
用官方提供的
,别用 H2 或 MySQL 版本改名凑合
在
中显式指定表前缀,避免大小写歧义:
如果已有数据,别手动改表名,而是用
并确保 schema 名一致
验证方式:连上数据库执行
(psql)或
,确认表名全小写且存在
Spring Batch 的坑多数藏在“默认行为”和“环境假设”里——它默认认为你用 H2、默认认为 JobParameters 是唯一的、默认认为数据库方言和脚本严丝合缝。一旦迁移跨库或跨环境,这些默认就变成故障点。最常被忽略的是:没验证
是否真在用你配的
,而不是悄悄 fallback 到内存模式。
JobLauncherNoUniqueBeanDefinitionExceptionJobLauncherspring-boot-starter-batch@EnableBatchProcessingJobLauncher@EnableBatchProcessingspring-boot-starter-batchspring-batch-coreJobLauncher@Primary@Bean
@Primary
public JobLauncher jobLauncher(JobRepository jobRepository) { ... }DataSourcespring.batch.initialize-schema=alwaysJobExecutionNotRunningExceptionJdbcCursorItemReaderDECIMAL(19,4)DoubleJdbcCursorItemReadersetRowMapperrowMapper.setRowMapper((rs, rowNum) -> {
BigDecimal amt = rs.getBigDecimal("amount");
if (amt == null) throw new IllegalStateException("amount is null at row " + rowNum);
return new Record(amt);
});StringBigDecimalLongWHERE status = 'PROCESSED''processed'logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUGJobRepositoryJobParametersJobInstanceAlreadyCompleteExceptionDataSourceschema-h2.sqlJobParametersnew JobParametersBuilder()
.addString("run.id", UUID.randomUUID().toString())
.addLong("time", System.currentTimeMillis())
.toJobParameters()JobParametersBuilder.addDate()JdbcPagingItemReaderJdbcCursorItemReaderJobRepositoryBATCH_JOB_INSTANCEbatch_job_instanceTable not foundschema-postgresql.sqlapplication.ymlspring:
batch:
jdbc:
table-prefix: BATCH_SET search_path TO public;\dtSELECT table_name FROM information_schema.tables WHERE table_schema='public';JobRepositoryDataSource