Spring Batch中的ItemReader:数据搬运工的“吸星大法”📚

Spring Batch中的ItemReader:数据搬运工的"吸星大法" 📚

副标题:从文件到数据库,如何优雅地"吸"数据?


一、ItemReader是谁?------数据搬运界的"吸尘器"

ItemReader 是Spring Batch中专门负责数据读取 的核心接口,它的使命只有一个:从各种数据源(文件、数据库、消息队列等)中"吸"出数据,交给后续的ItemProcessorItemWriter处理。它的read()方法就像吸尘器的开关,每次调用"吸"一条数据,直到返回null(表示数据吸完了)。

接口定义与核心逻辑:

java 复制代码
public interface ItemReader<T> {
    T read() throws Exception; // 吸一条,吸不动了返回null
}

适用场景

  • 从CSV文件读取百万条订单数据
  • 从数据库分页查询用户信息
  • 从消息队列消费待处理消息

二、ItemReader的"十八般武艺"------主要实现类型

Spring Batch为不同数据源提供了丰富的内置实现,开发者无需重复造轮子。

1. 文件读取类

  • FlatFileItemReader :专治CSV、TXT等平面文件,支持分隔符、固定长度等格式。

    java 复制代码
    // 示例:读取CSV文件并映射为Person对象
    @Bean
    public FlatFileItemReader<Person> reader() {
        return new FlatFileItemReaderBuilder<Person>()
            .resource(new ClassPathResource("data.csv"))
            .delimited().names("name", "age")
            .targetType(Person.class)
            .build();
    }
  • StaxEventItemReader:解析XML文件,支持XSD验证。

2. 数据库读取类

  • JdbcCursorItemReader:基于游标逐行读取,适合大数据量(但需注意内存占用)。
  • JdbcPagingItemReader:分页查询,避免一次性加载所有数据(内存友好)。
  • JpaPagingItemReader:基于JPA的分页读取,集成ORM框架。

3. 消息队列与NoSQL

  • JmsItemReader:从JMS队列消费消息。
  • MongoItemReader:读取MongoDB数据,支持分页和排序。

4. 自定义场景

  • ListItemReader:直接读取内存中的List(调试神器)。
  • 自定义ItemReader :实现ItemReader接口,适配特殊数据源(如API接口)。

三、ItemReader的"记忆大师"------状态管理与重启机制

Spring Batch通过ItemStream接口实现状态管理,确保任务崩溃后能"断点续吸"。

ItemStream三剑客:

  1. open():初始化读取位置(如从数据库游标或文件行号开始)。
  2. update() :将当前读取状态(如行号)保存到ExecutionContext
  3. close():释放资源(如关闭文件句柄或数据库连接)。

示例

  • 若任务在读取到第1000行时崩溃,重启后open()会根据保存的状态跳过前1000行。

四、ItemReader的"容错秘籍"------异常处理

读取数据时难免遇到脏数据或网络抖动,Spring Batch提供灵活的错误处理策略:

  1. 跳过脏数据 :配置SkipPolicy,如跳过格式错误的CSV行。
  2. 重试机制:对可重试异常(如网络超时)设置重试次数。
  3. 限流控制 :设置skipLimit(10),最多跳过10条错误数据。

代码示例

java 复制代码
public Step step() {
    return stepBuilderFactory.get("step")
        .<Person, Person>chunk(100)
        .reader(reader())
        .faultTolerant()
        .skipLimit(10)
        .skip(FlatFileParseException.class) // 跳过解析异常
        .retryLimit(3)
        .retry(DeadlockLoserDataAccessException.class) // 重试数据库死锁
        .build();
}

五、实战对比:游标 vs. 分页------数据库读取的"左右互搏"

1. JdbcCursorItemReader(游标)

  • 原理:通过JDBC游标逐行读取,保持数据库连接直到读完。
  • 优点:适合大数据量,内存占用低。
  • 缺点:长事务可能锁表,连接占用时间长。

2. JdbcPagingItemReader(分页)

  • 原理:分页查询(如每页1000条),多次短事务完成读取。
  • 优点:避免长事务,内存更可控。
  • 缺点:分页SQL性能依赖数据库优化(如索引)。

选择建议

  • 数据量极大且无需实时性 → 游标
  • 高并发或需避免锁表 → 分页

六、自定义ItemReader开发------手把手打造"专属吸管"

若内置实现不满足需求,可自定义ItemReader:

示例:从API分页读取数据

java 复制代码
public class ApiItemReader implements ItemReader<Data>, ItemStream {
    private int page = 0;
    private Iterator<Data> currentPage;

    @Override
    public Data read() {
        if (currentPage == null || !currentPage.hasNext()) {
            currentPage = fetchNextPage(page++).iterator(); // 调用API获取下一页
        }
        return currentPage.hasNext() ? currentPage.next() : null;
    }

    @Override
    public void open(ExecutionContext context) {
        page = context.getInt("page", 0); // 从上下文恢复页码
    }

    @Override
    public void update(ExecutionContext context) {
        context.putInt("page", page); // 保存当前页码
    }
}

七、最佳实践------老司机的"吸数据"心得

  1. 合理配置Chunk大小

    • 太大 → 内存溢出(如10000条一次)
    • 太小 → 事务开销高(如10条一次)
    • 建议:根据数据量和内存测试,一般100~1000条。
  2. 监控与日志

    • 通过StepExecutionListener记录读取速度、错误率。
    • 集成Spring Boot Actuator查看批处理指标。
  3. 资源释放

    • 确保ItemStream.close()正确关闭资源(如文件句柄、数据库连接)。

总结

ItemReader是Spring Batch数据处理的"第一公里",无论是文件解析、数据库查询还是自定义数据源,它都能以高效、可靠、可重启的方式完成任务。掌握其核心机制与最佳实践,你的批处理任务将如虎添翼!

相关推荐
FlyWIHTSKY2 分钟前
idea中push拒绝,merge,rebase的区别
java·ide·intellij-idea
Code季风7 分钟前
深入实战 —— Protobuf 的序列化与反序列化详解(Go + Java 示例)
java·后端·学习·rpc·golang·go
Leslie_Lei31 分钟前
【pdf】Java代码生成PDF
java·pdf
想用offer打牌1 小时前
关于Seata的一个小issue...😯
java·后端·架构
飞翔的佩奇1 小时前
基于Spring+MyBatis+MySQL实现的监考安排与查询系统设计与实现(附源码+数据库)推荐!
java·数据库·mysql·spring·毕业设计·mybatis·监考安排与查询
weixin_438335401 小时前
Lombok常用注解总结
java·lombok注解
昂子的博客2 小时前
Springboot仿抖音app开发之Nacos 分布式服务与配置中心(进阶)
java·spring boot·redis·后端·mysql·ip
还是鼠鼠2 小时前
JavaWeb RESTful 开发规范入门
java·数据库·spring boot·后端·spring·mybatis·restful
爱码少年2 小时前
shel脚本重启Jar服务
java·jar
李艺为2 小时前
framework.jar三个jar包的区别
java·pycharm·jar