Spring Batch读取多行多格式文件实现关联记录聚合的方案问询
Spring Batch多行关联记录读取实现方案
你预想的实现逻辑是完全可行的,Spring Batch官方的多行记录读取方案本质就是基于SingleItemPeekableItemReader做上层封装,不需要更换方案,只需要补充类型统一和聚合逻辑即可。
核心实现思路
- 定义统一标记接口,让
ObjectA和ObjectB都实现该接口,解决peek()方法返回值类型不统一的问题 - 自定义
ItemReader<ObjectA>,内部持有SingleItemPeekableItemReader作为委托读取器 - 维护当前正在组装的
ObjectA实例,循环peek下一条记录判断类型,完成B列表的聚合或者A的返回
代码实现
统一标记接口与实体类
// 统一记录标记接口 public interface FileRecord {} // ObjectA实现标记接口 public class ObjectA implements FileRecord { private List<ObjectB> bList = new ArrayList<>(); // 其他原有属性、getter、setter方法 public List<ObjectB> getBList() { return bList; } } // ObjectB实现标记接口 public class ObjectB implements FileRecord { // 原有属性、getter、setter方法 }
自定义聚合读取器
public class AggregatingObjectAReader implements ItemReader<ObjectA> { private SingleItemPeekableItemReader<FileRecord> delegate; // 存储当前正在组装的ObjectA实例 private ObjectA currentObjectA; @Override public ObjectA read() throws Exception { // 首次读取或上一个ObjectA已返回,读取新的ObjectA if (currentObjectA == null) { FileRecord record = delegate.read(); if (record == null) { return null; } currentObjectA = (ObjectA) record; } while (true) { FileRecord nextRecord = delegate.peek(); // 已到文件末尾,返回当前组装完成的ObjectA if (nextRecord == null) { ObjectA result = currentObjectA; currentObjectA = null; return result; } // 下一条是新的ObjectA,返回当前组装完成的ObjectA if (nextRecord instanceof ObjectA) { ObjectA result = currentObjectA; currentObjectA = null; return result; } // 下一条是关联的ObjectB,读取后加入当前ObjectA的列表 if (nextRecord instanceof ObjectB) { ObjectB bRecord = (ObjectB) delegate.read(); currentObjectA.getBList().add(bRecord); } } } // 注入委托读取器 public void setDelegate(SingleItemPeekableItemReader<FileRecord> delegate) { this.delegate = delegate; } }
Bean配置示例
@Bean public FlatFileItemReader<FileRecord> flatFileItemReader() { // 复用你已经实现的原有配置:使用PatternMatchingCompositeLineMapper // 分别将A、B类型行映射为ObjectA、ObjectB实例即可 } @Bean public SingleItemPeekableItemReader<FileRecord> peekableItemReader() { SingleItemPeekableItemReader<FileRecord> reader = new SingleItemPeekableItemReader<>(); reader.setDelegate(flatFileItemReader()); return reader; } @Bean public AggregatingObjectAReader aggregatingObjectAReader() { AggregatingObjectAReader reader = new AggregatingObjectAReader(); reader.setDelegate(peekableItemReader()); return reader; }
注意事项
- 该实现默认输入文件符合约定格式:首行是A类型记录,所有B类型记录都跟在对应A的后面,无单独游离的B记录。如果需要兼容异常格式,可补充对应的类型校验和异常处理逻辑
- 不需要额外引入其他多行处理组件,该方案就是Spring Batch官方推荐的多行关联记录处理实现方式
内容的提问来源于stack exchange,提问作者RoNoWhe
相关产品推荐
相关产品推荐

