
本文详解如何使用 spring batch 高效读取数据库大批量数据、进行批处理逻辑加工,并以 list 形式整体发送至第三方服务,突破默认单条处理限制,实现高性能、可伸缩的批量集成方案。
本文详解如何使用 spring batch 高效读取数据库大批量数据、进行批处理逻辑加工,并以 list 形式整体发送至第三方服务,突破默认单条处理限制,实现高性能、可伸缩的批量集成方案。
在 Spring Batch 中,ItemReader、ItemProcessor 和 ItemWriter 默认以“逐条(per-item)”语义设计:ItemProcessor 确实每次只接收一个对象进行转换或增强,但这并不意味着无法实现“按批次(chunk)整体处理+批量提交”。关键在于——Spring Batch 的核心抽象单位是 Chunk(块),而非 Item(项)。Chunk 是框架内置的事务边界和数据聚合单元,天然支持将 N 条记录聚合成 List,在 ItemWriter 阶段统一处理。
✅ 正确实践:利用 Chunk + 自定义 ItemWriter 实现 List 批量发送
以下是一个典型配置示例(基于 Java Config + Spring Boot 3.x):
@Bean
public Job processLargeDataJob(JobRepository jobRepository, Step step) {
return new JobBuilder("processLargeDataJob", jobRepository)
.start(step)
.build();
}
@Bean
public Step processLargeDataStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("processLargeDataStep", jobRepository)
.<user user>chunk(100, transactionManager) // 每次读取并处理 100 条为一个 chunk
.reader(jdbcCursorItemReader()) // 从 DB 读取 User 列表(逐条流式)
.processor(userProcessor()) // 单条增强(如补全部门信息、计算积分等)
.writer(batchApiWriter()) // 【重点】此处接收 List<user>,整体调用第三方 API
.build();
}
@Bean
public JdbcCursorItemReader<user> jdbcCursorItemReader() {
return new JdbcCursorItemReaderBuilder<user>()
.name("userReader")
.dataSource(dataSource)
.sql("SELECT id, name, email FROM users WHERE status = 'ACTIVE'")
.rowMapper(new BeanPropertyRowMapper(User.class))
.build();
}
@Bean
public ItemProcessor<user user> userProcessor() {
return user -> {
// 示例:单条业务增强(非批量逻辑)
user.setProcessedAt(LocalDateTime.now());
user.setScore(calculateScore(user));
return user;
};
}
@Bean
public ItemWriter<user> batchApiWriter() {
return users -> {
// ✅ users 是 List<user>,大小 ≈ chunk size(如 100)
if (!users.isEmpty()) {
// 调用第三方 HTTP 接口(推荐使用 WebClient 或 RestTemplate 批量 POST)
String response = thirdPartyApiClient.batchSend(users);
log.info("Successfully sent {} users to third party, response: {}", users.size(), response);
}
};
}</user></user></user></user></user></user></user>
⚠️ 关键注意事项
- Chunk Size 合理设置:过小(如 10)导致频繁网络调用;过大(如 10000)可能引发内存溢出或事务超时。建议结合目标 API 的吞吐能力、JVM 堆内存及数据库游标性能压测后确定(通常 50–500 是安全起点)。
- Writer 必须幂等 & 可重试:因 chunk 级事务失败会触发重试,batchApiWriter 中的远程调用需确保重复提交不产生副作用(例如通过唯一请求 ID + 幂等令牌)。
- 避免在 Processor 中聚合数据:ItemProcessor 是无状态、单条处理的,切勿试图在其中缓存 List——这会破坏并行性、线程安全性及重启恢复能力。所有批量逻辑必须下沉到 ItemWriter。
- 启用 Restartability:确保 ItemReader 支持重启(如 JdbcPagingItemReader 或带 saveState=true 的 JdbcCursorItemReader),以便作业中断后能从断点续跑,而非全量重刷。
? 总结
Spring Batch 本身即为“批量”而生——它不强制你手动拼装 List,而是通过 chunk 机制自动将流式读取的数据聚合成 List,并在 ItemWriter 阶段交由你统一处置。真正需要转变的是思维:把“批量发送”视为 Writer 的职责,而非绕过框架自建缓冲池。遵循这一模式,即可在保持 Spring Batch 强大事务管理、监控、重启能力的同时,完美支撑高吞吐第三方集成场景。










