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

Spring Batch如何插入List<DTO>类型记录?Excel行转多记录入库问询

需求可实现,解决方案如下

错误原因分析

你当前的代码存在两个核心问题:

  1. 泛型类型错误:JdbcBatchItemWriter泛型指定为List<student>,意味着它会把List作为单个待处理Item,但BeanPropertyItemSqlParameterSourceProvider会尝试从ArrayList对象中读取Name属性——显然List并没有这个属性,因此抛出属性不可读异常。
  2. 参数名不匹配:SQL中的:Name参数与JavaBean属性命名规范不符(JavaBean属性名通常为小写开头,如name,对应getName() getter方法),无法正确映射。

完整解决方案

1. 定义Excel行数据接收类

假设Excel一行包含多组学生信息(如name1,class1,rank1,name2,class2,rank2),先定义类接收整行数据:

public class MultiStudentRow {
    private String name1;
    private String class1;
    private Integer rank1;
    private String name2;
    private String class2;
    private Integer rank2;

    // 生成所有属性的getter/setter方法
}

2. 实现ItemProcessor拆分单行数据

编写处理器将整行数据拆分为多个Student对象:

public class MultiStudentRowProcessor implements ItemProcessor<MultiStudentRow, List<Student>> {
    @Override
    public List<Student> process(MultiStudentRow item) throws Exception {
        List<Student> students = new ArrayList<>();
        // 处理第一组学生数据
        if (item.getName1() != null && !item.getName1().isEmpty()) {
            Student student1 = new Student();
            student1.setName(item.getName1());
            student1.setClass(item.getClass1());
            student1.setRank(item.getRank1());
            student1.setStatus("A");
            students.add(student1);
        }
        // 处理第二组学生数据(可根据Excel列数扩展更多组)
        if (item.getName2() != null && !item.getName2().isEmpty()) {
            Student student2 = new Student();
            student2.setName(item.getName2());
            student2.setClass(item.getClass2());
            student2.setRank(item.getRank2());
            student2.setStatus("A");
            students.add(student2);
        }
        return students;
    }
}

3. 修正JdbcBatchItemWriter配置

将泛型改为单个Student对象,并匹配正确的参数名:

@Bean
public JdbcBatchItemWriter<Student> jdbcStudentWriter(DataSource dataSource4) {
    return new JdbcBatchItemWriterBuilder<Student>()
        .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
        .sql("INSERT INTO students (name, class, rank, status) VALUES (:name, :class, :rank, :status)")
        .dataSource(dataSource4)
        .build();
}

4. 配置批量处理Writer

由于处理器返回List<Student>,需要自定义Writer遍历列表并调用JDBC Writer:

public class ListStudentItemWriter implements ItemWriter<List<Student>> {
    private final JdbcBatchItemWriter<Student> jdbcWriter;

    public ListStudentItemWriter(JdbcBatchItemWriter<Student> jdbcWriter) {
        this.jdbcWriter = jdbcWriter;
    }

    @Override
    public void write(List<? extends List<Student>> items) throws Exception {
        List<Student> allStudents = items.stream()
            .flatMap(List::stream)
            .collect(Collectors.toList());
        jdbcWriter.write(allStudents);
    }
}

// 注册Bean
@Bean
public ListStudentItemWriter listStudentItemWriter(JdbcBatchItemWriter<Student> jdbcWriter) {
    return new ListStudentItemWriter(jdbcWriter);
}

5. 配置Step与Job

组装完整的批处理流程:

@Bean
public Step excelToDbStep(ItemReader<MultiStudentRow> excelReader,
                          MultiStudentRowProcessor processor,
                          ListStudentItemWriter listWriter,
                          PlatformTransactionManager transactionManager,
                          JobRepository jobRepository) {
    return new StepBuilder("excelToDbStep", jobRepository)
        .<MultiStudentRow, List<Student>>chunk(10, transactionManager)
        .reader(excelReader)
        .processor(processor)
        .writer(listWriter)
        .build();
}

// 配置Job
@Bean
public Job excelImportJob(Step excelToDbStep, JobRepository jobRepository) {
    return new JobBuilder("excelImportJob", jobRepository)
        .start(excelToDbStep)
        .build();
}

内容的提问来源于stack exchange,提问作者Arun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 20:15:34