Spring Batch如何合并两个定长文件数据实例化对象(无数据库)
Spring Batch 无数据库关联两个定长文件实现方案
针对两个按id关联的定长文件、无数据库权限需要拼接生成Foo对象的场景,可根据数据量大小选择以下两种实现方式,全程不需要数据库暂存:
方案1:小数据量场景(单文件可被JVM内存承载)
- 前置步骤:配置独立Tasklet在业务处理逻辑执行前运行,读取F2全量文件,将解析出的(id, C, D)字段存入内存
Map<ID类型, 自定义CD字段封装对象>结构,以id为key。 - 主处理步骤:配置
FlatFileItemReader读取F1定长文件,通过FixedLengthTokenizer解析每行得到(id, A, B)字段;在ItemProcessor阶段直接根据当前id从预加载的内存Map中取出对应的C、D字段值,直接传入构造函数实例化Foo对象。 - 后续直接接入你需要的校验、输出逻辑对应的ItemProcessor、ItemWriter即可。
注意:如果F2数据量超过JVM堆内存可承载范围,不要使用该方案,避免OOM。
方案2:大数据量场景(单文件超过内存承载上限,如百万级以上记录)
核心思路是先将两个文件按id排序,再通过双指针流式匹配,全程内存占用为常数级,不需要加载全量数据:
- 排序步骤:配置两个独立Tasklet,分别对F1、F2做外排序,输出按id升序排列的临时文件。外排序过程仅占用固定大小的内存缓冲区,不会出现内存溢出问题。
- 自定义双源ItemReader:内部维护两个分别指向排序后F1、F2文件的流读取指针,匹配逻辑如下:
- 初始化阶段分别读取两个文件的首条记录,获取对应id
- 循环匹配逻辑:若两个记录id相等,直接拼接A、B、C、D字段实例化Foo对象返回,随后两个指针各自读取下一条记录;若F1当前id小于F2当前id,说明该条F1记录无匹配的F2数据,可按业务需求做丢弃/填充默认值处理,随后F1指针读取下一条;若F2当前id小于F1当前id,F2指针读取下一条
- 两个文件流均读取完成后,返回null标识数据读取完毕
- 后续同样直接接入对应处理、写入组件即可。
配置注意事项
- 定长文件字段解析直接使用Spring Batch内置的
FixedLengthTokenizer,按字段位置配置起止下标即可,无需自行编写解析逻辑。 - 若两个文件存在重复id,需要在排序步骤提前做去重或聚合处理,避免双指针匹配时出现错位。
- 排序生成的临时文件可绑定
DeleteFileOnCompletionListener,在步骤执行完成后自动清理,无需手动删除。
内容的提问来源于stack exchange,提问作者Zidani Mehdi
相关产品推荐
相关产品推荐

