Spring Boot Batch处理:新增age列并根据出生日期计算年龄
Spring Boot Batch实现CSV转H2并新增计算年龄列
核心思路
age列是通过出生日期计算得出的,不需要在LineMapper中定义(因为CSV源数据里没有这个字段),而是在ItemProcessor中完成计算并赋值,同时需要调整实体类和数据库表结构来存储age字段。
1. 调整User实体类
在User实体中新增age字段,同时保留原有的date(出生日期)字段:
@Entity @Table(name = "users") public class User { // 原有字段... @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") private LocalDateTime date; private Integer age; // 新增年龄字段 // 生成age的getter、setter方法 // 其他字段的getter、setter... }
2. 确保H2数据库表包含age列
- 如果使用JPA自动建表(配置
spring.jpa.hibernate.ddl-auto=update),Hibernate会自动根据实体类在H2中生成包含age列的users表。 - 如果手动建表,SQL语句需添加
age列:
CREATE TABLE users ( id BIGINT PRIMARY KEY, person_id VARCHAR(255), first_name VARCHAR(255), last_name VARCHAR(255), email VARCHAR(255), gender VARCHAR(255), country VARCHAR(255), date TIMESTAMP, age INT -- 新增年龄列 );
3. 修改ItemProcessor实现年龄计算
在UserProcessor中,将UserDTO的出生日期转换为LocalDate,调用年龄计算方法后赋值给User实体的age字段:
public class UserProcessor implements ItemProcessor<UserDTO, User> { @Override public User process(UserDTO userDTO) throws Exception { User user = new User(); // 映射CSV读取到的字段 user.setId(userDTO.getId()); user.setPerson_id(userDTO.getPerson_id()); user.setFirst_name(userDTO.getFirst_name()); user.setLast_name(userDTO.getLast_name()); user.setEmail(userDTO.getEmail()); user.setGender(userDTO.getGender()); user.setCountry(userDTO.getCountry()); user.setDate(userDTO.getDate()); // 计算并设置年龄 if (userDTO.getDate() != null) { LocalDate birthDate = userDTO.getDate().toLocalDate(); int age = calculateAge(birthDate, LocalDate.now()); user.setAge(age); } else { user.setAge(0); } return user; } // 年龄计算逻辑 private int calculateAge(LocalDate birthDate, LocalDate currentDate) { if (birthDate != null && currentDate != null) { return Period.between(birthDate, currentDate).getYears(); } return 0; } }
4. LineMapper仅映射CSV原有字段
LineMapper只需要处理CSV中存在的字段,不需要配置age相关映射。示例配置如下:
@Bean public FlatFileItemReader<UserDTO> userReader() { FlatFileItemReader<UserDTO> reader = new FlatFileItemReader<>(); reader.setResource(new ClassPathResource("users.csv")); DefaultLineMapper<UserDTO> lineMapper = new DefaultLineMapper<>(); // 配置CSV字段分隔和列名(对应CSV中的列) DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); tokenizer.setNames("id", "person_id", "first_name", "last_name", "email", "gender", "country", "date"); tokenizer.setDelimiter(","); // 字段映射到UserDTO,处理日期格式转换 BeanWrapperFieldSetMapper<UserDTO> fieldSetMapper = new BeanWrapperFieldSetMapper<>(); fieldSetMapper.setTargetType(UserDTO.class); // 注册LocalDateTime类型转换,适配CSV中的日期格式 fieldSetMapper.registerCustomEditor(LocalDateTime.class, new PropertyEditorSupport() { @Override public void setAsText(String text) throws IllegalArgumentException { try { Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(text); setValue(date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()); } catch (ParseException e) { setValue(null); } } }); lineMapper.setLineTokenizer(tokenizer); lineMapper.setFieldSetMapper(fieldSetMapper); reader.setLineMapper(lineMapper); return reader; }
内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu
相关产品推荐
相关产品推荐

