You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 17:24:02