跳转到主内容
极星编程网:以代码为星,赴技术山海!

如何在Java中配置Spring Batch批处理环境_Java数据迁移

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

相关文章