
spring batch 并非一次性加载全部数据,而是基于流式 i/o 与分块(chunk)机制,按指定大小(如每批 10 行)逐批读取、处理、写入,兼顾内存效率与事务一致性。
Spring Batch 的核心优势之一,正在于其流式分块处理(Chunk-Oriented Processing)模型——它彻底规避了“全量加载→全量处理→全量输出”的内存陷阱。以您提出的 10,000 行 CSV 场景为例(chunkSize = 10),整个流程严格遵循以下循环逻辑:
- Reader 按需拉取:FlatFileItemReader 底层封装 BufferedReader,仅在当前 chunk 需要时,从文件流中顺序读取 最多 10 行(跳过表头后),解析为 Student 对象并缓存在内存中;
- Processor 批量转换:processor 接收这 10 个对象组成的集合(实际为单个对象的逐个调用,但受 chunk 事务约束),执行业务逻辑(如字段追加 !);
- Writer 原子写入:FlatFileItemWriter 将该批次 10 个处理后的对象,通过 LineAggregator 格式化为 CSV 行,并追加写入目标文件(非覆盖);
- 事务提交:整个读-处理-写三阶段被包裹在一个数据库事务中(由 PlatformTransactionManager 管理),任一环节失败则回滚本 chunk,确保数据一致性。
✅ 正确理解:整个过程重复 10,000 ÷ 10 = 1,000 次,峰值内存仅需容纳约 10 条记录 + 开销,而非 10,000 条。
⚠️ 关键注意事项:
- Reader 不是“预加载”:reader() 方法仅初始化 Reader 实例(如您的代码中 System.out.println("reader") 在 Job 启动时打印),真正读取发生在 Step 执行时按需触发;
- Writer 必须支持追加:FlatFileItemWriter 默认使用 FileSystemResource 时,若目标文件已存在,需显式配置 setAppendAllowed(true)(默认 false,会清空重写);
- 事务边界即 chunk 边界:chunk(10) 意味着每处理 10 条即提交一次事务。若需更高吞吐,可适度增大 chunk size(需权衡内存与事务粒度);
- 数据库场景同理:JDBC JdbcCursorItemReader 或 JdbcPagingItemReader 同样支持分页/游标式流读取,配合 JdbcBatchItemWriter 批量插入,实现“读 10 条 → 处理 → 写入 dbB 的 10 条”。
以下为数据库迁移的简化伪代码示意(基于 JdbcCursorItemReader):
@Bean public JdbcCursorItemReaderdbReader(DataSource dataSource) { JdbcCursorItemReader reader = new JdbcCursorItemReader<>(); reader.setDataSource(dataSource); reader.setSql("SELECT id, name, amount FROM account WHERE status = 'ACTIVE'"); reader.setRowMapper((rs, rowNum) -> new TransferRecord(rs.getLong("id"), rs.getString("name"), rs.getBigDecimal("amount")) ); return reader; } @Bean public JdbcBatchItemWriter dbWriter(DataSource dataSource) { JdbcBatchItemWriter writer = new JdbcBatchItemWriter<>(); writer.setDataSource(dataSource); writer.setSql("INSERT INTO account_bak (id, name, amount) VALUES (?, ?, ?)"); writer.setItemPreparedStatementSetter((item, ps) -> { ps.setLong(1, item.getId()); ps.setString(2, item.getName()); ps.setBigDecimal(3, item.getAmount()); }); return writer; }
总结而言,Spring Batch 的价值远不止“多写了几个类”——它通过标准化的流式分块、声明式事务、失败重启、监控统计等能力,将原本易出错的手动批处理,转化为可运维、可伸缩、可恢复的企业级批量作业。合理配置 chunkSize、选择合适 Reader/Writer、理解事务边界,是发挥其威力的关键前提。










