Spring Batch如何插入List<DTO>类型记录?Excel行转多记录入库问询
需求可实现,解决方案如下
错误原因分析
你当前的代码存在两个核心问题:
- 泛型类型错误:
JdbcBatchItemWriter泛型指定为List<student>,意味着它会把List作为单个待处理Item,但BeanPropertyItemSqlParameterSourceProvider会尝试从ArrayList对象中读取Name属性——显然List并没有这个属性,因此抛出属性不可读异常。 - 参数名不匹配: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
相关产品推荐
相关产品推荐

