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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 07:11:05