Spring Boot Batch DB转CSV报错:Bean属性‘ID’不可读或Getter无效
解决Spring Batch导出CSV时的NotReadablePropertyException问题
错误信息
org.springframework.beans.NotReadablePropertyException: Invalid property 'ID' of bean class [com.example.springbatchprocessdbtocsv.model.User]: Bean property 'ID' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
问题原因
错误源于数据库列名与实体类属性名的大小写不匹配,且Spring Batch字段映射严格遵循JavaBean规范:
- 数据库表主键列是大写的
"ID" - 实体父类
BaseEntity中定义的主键属性是小写的id,对应getter方法为getId() - 若Spring Batch配置(如
FlatFileItemWriter的字段映射)中使用大写ID作为字段名,框架会尝试访问实体类的ID属性,但实体类仅存在小写id属性,因此抛出不可读异常。
解决方案
1. 修正ItemWriter的字段映射配置
找到Spring Batch写入器配置,将大写ID改为实体类对应的小写属性名id。
错误配置示例:
@Bean public FlatFileItemWriter<User> writer() { return new FlatFileItemWriterBuilder<User>() .name("userItemWriter") .resource(new FileSystemResource("users.csv")) .delimited() .names("ID", "FIRST_NAME", "LAST_NAME", "EMAIL", "GENDER", "COUNTRY", "BIRTHDAY", "AGE") .build(); }
修正后配置:
@Bean public FlatFileItemWriter<User> writer() { return new FlatFileItemWriterBuilder<User>() .name("userItemWriter") .resource(new FileSystemResource("users.csv")) .delimited() .names("id", "firstName", "lastName", "email", "gender", "country", "birthday", "age") .build(); }
2. (可选)保持CSV列名为大写ID
若需要CSV文件显示大写ID列名,可通过DelimitedLineAggregator自定义列名,同时保证属性映射正确:
@Bean public FlatFileItemWriter<User> writer() { DelimitedLineAggregator<User> lineAggregator = new DelimitedLineAggregator<>(); lineAggregator.setDelimiter(","); lineAggregator.setFieldExtractor(new BeanWrapperFieldExtractor<>() {{ setNames(new String[]{"id", "firstName", "lastName", "email", "gender", "country", "birthday", "age"}); }}); return new FlatFileItemWriterBuilder<User>() .name("userItemWriter") .resource(new FileSystemResource("users.csv")) .headerCallback(writer -> writer.write("ID,FIRST_NAME,LAST_NAME,EMAIL,GENDER,COUNTRY,BIRTHDAY,AGE")) .lineAggregator(lineAggregator) .build(); }
3. 修正UserProcessor的代码错误
处理器中存在参数引用错误,将from改为方法参数user,同时优化性别映射逻辑:
public class UserProcessor implements ItemProcessor<User, User> { @Override public User process(User user) throws Exception { return User.builder() .personId(user.getPersonId()) .firstName(user.getFirstName()) .lastName(user.getLastName()) .email(user.getEmail()) .country(user.getCountry()) .birthday(user.getBirthday()) .gender(mapGender(user.getGender())) .age(user.getAge()) .build(); } private Gender mapGender(Gender gender) { if (gender == null) return null; return gender.name().equalsIgnoreCase("male") ? Gender.MALE : Gender.FEMALE; } }
额外检查
确认BaseEntity的@Getter注解正常生成getId()方法,Lombok配置生效,实体类属性符合JavaBean规范。
内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu
相关产品推荐
相关产品推荐

