乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • 学习路径
  • 第1章 批处理概述与 Spring Batch 核心理念

    • Spring Batch 概述
    • Job-Instance-Execution 三层生命周期
    • 三层架构
    • Chunk 处理模型
    • Tasklet 处理模型
  • 第2章 Job与作业配置

    • Job 详解
    • Job 配置
    • JobLauncher 详解
    • JobParameters 详解
    • JobRepository 详解
  • 第3章 Step与执行模型

    • Step 详解
    • Step 配置
    • ExecutionContext 详解
    • ItemStream 与状态管理
    • StepScope 与 JobScope
  • 第4章 ItemReader数据读取

    • ItemReader 详解
    • FlatFileItemReader 详解
    • JdbcItemReader 详解
    • MultiResourceItemReader 详解
  • 第5章 ItemProcessor 数据处理

    • ItemProcessor 详解
  • 第6章 ItemWriter 数据写出

    • ItemWriter 详解
    • FlatFileItemWriter 详解
    • CompositeItemWriter 详解
    • JdbcBatchItemWriter 详解
  • 第7章 Chunk 处理与事务边界

    • Chunk 处理模型详解
    • 事务边界
  • 第8章 作业参数与启动

    • 命令行与 Web 启动
  • 第9章 监听器与拦截器

    • 监听器详解
  • 第10章 重启重试与跳过策略

    • 重启与重试
    • 跳过策略
  • 第11章 作业流与条件决策

    • 作业流与条件决策
  • 第12章 分区与并行处理

    • 分区详解
    • 并行 Step 与 Split
  • 第13章 与 Spring Boot 集成实践

    • Spring Boot 集成
  • 第15章 运维与监控

    • 大作业设计模式
    • 运维与监控

JdbcBatchItemWriter 详解

本章定位:深入掌握 Spring Batch 最高频的数据库 Writer——JdbcBatchItemWriter,从参数绑定到性能调优。

定义与作用

JdbcBatchItemWriter 使用 JDBC Batch API(PreparedStatement.addBatch() + executeBatch())将数据批量写入数据库。它将 Chunk 中的 N 条数据通过 N 次 addBatch() 后一次性 executeBatch(),极大减少网络往返。

小崔处理杨英每日 5000 条订单写入时的体验:

"不写 JDBC 循环、不写 Connection 管理、不写 try-catch。JdbcBatchItemWriter 帮我把一切包裹在 Chunk 事务里。5000 条 = 100 次 executeBatch(),网络往返从 5000 次降到 100 次。"

核心原理

三种 ParameterSourceProvider

Provider数据输入适用场景
BeanPropertyItemSqlParameterSourceProviderPOJODTO/Entity 的 getter 自动映射到 :paramName
MapItemSqlParameterSourceProviderMap动态构建参数集合
自定义任意复杂 SQL、聚合计算

完整示例

场景一:标准 Entity 写入

@Bean
public JdbcBatchItemWriter<StudentEntity> standardStudentWriter(DataSource dataSource) {
    return new JdbcBatchItemWriterBuilder<StudentEntity>()
            .dataSource(dataSource)
            .sql("INSERT INTO students (student_id, name, email, age, import_time) "
               + "VALUES (:studentId, :name, :email, :age, :importTime) "
               + "ON DUPLICATE KEY UPDATE name = VALUES(name), email = VALUES(email), age = VALUES(age)")
            .itemSqlParameterSourceProvider(
                new BeanPropertyItemSqlParameterSourceProvider<>())
            .assertUpdates(true)
            .build();
}

场景二:多数据源 Writer

@Bean
public JdbcBatchItemWriter<AuditLog> auditWriter(
        @Qualifier("auditDataSource") DataSource auditDataSource) {
    return new JdbcBatchItemWriterBuilder<AuditLog>()
            .dataSource(auditDataSource)  // 走单独的审计数据源
            .sql("INSERT INTO audit_log (job_name, step_name, record_count, timestamp) "
               + "VALUES (:jobName, :stepName, :recordCount, :timestamp)")
            .itemSqlParameterSourceProvider(log -> {
                MapSqlParameterSource params = new MapSqlParameterSource();
                params.addValue("jobName", log.jobName());
                params.addValue("stepName", log.stepName());
                params.addValue("recordCount", log.recordCount());
                params.addValue("timestamp", LocalDateTime.now());
                return params;
            })
            .build();
}

性能对比:

方案10 万条写入内存占用
JdbcTemplate.update() 逐条~120s低
JdbcBatchItemWriter chunk=50~8s (15x)低
JdbcBatchItemWriter chunk=1000~2s (60x)中

易错场景与避坑

反例一:SQL 中参数名和 POJO 属性名不匹配

// ❌ SQL 中 :studentName 但 POJO 属性是 name
.sql("INSERT INTO students (name) VALUES (:studentName)")
// BeanPropertyItemSqlParameterSourceProvider 找不到 studentName → 报错

反例二:忘记设置 assertUpdates

// ❌ 默认 assertUpdates=false → SQL 执行了 0 行也不报错
.sql("UPDATE students SET status='ACTIVE' WHERE id=:id")
// 如果 id 不存在 → 0 rows affected → 静默跳过 → 数据丢失!

正确做法:对于 INSERT/UPDATE 必须 assertUpdates(true)。

面试高频考点

Q1:JdbcBatchItemWriter 和 JpaItemWriter 的性能差异?

JdbcBatchItemWriter 使用 executeBatch() 一次性提交多条 SQL,1 次网络往返。JpaItemWriter 逐条 entityManager.merge(),N 次网络往返。大数据量下 JDBC 版本快 5-10 倍。但 JPA 版本支持级联和实体状态管理。

Q2:如何处理 Writer 中部分成功部分失败的情况?

在 Chunk 模式下不可行——一个 Chunk 的写入在同一个事务中,要么全成功要么全回滚。如果某些行预期会失败,需要在 Processor 阶段过滤或标记,或在 Writer 中使用 faultTolerant().skip()。


上一章:FlatFileItemWriter 详解下一章:CompositeItemWriter 详解

上一页
CompositeItemWriter 详解