Spring Batch字符串日期转java.sql.Date入库类型不匹配问题
我之前也碰到过一模一样的问题!Spring Batch默认的属性绑定器没法自动把字符串格式的日期转换成java.sql.Date类型,所以才会抛出这个typeMismatch错误。给你几个靠谱的解决办法,挑适合你项目的来用:
方法1:在ItemProcessor里手动转换(最直接)
Spring Batch的ItemProcessor本来就是用来做数据转换、清洗的,咱们可以在这里把文件模型里的字符串日期转成数据库实体需要的java.sql.Date:
@Component public class SkuDataProcessor implements ItemProcessor<VSOGOutOfStockSkuDataForBatchJob, VSOGOutOfStockSkuData> { // 注意这里的日期格式要和文件里的完全匹配,你的是yyyy-MM-dd private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @Override public VSOGOutOfStockSkuData process(VSOGOutOfStockSkuDataForBatchJob fileModel) throws Exception { VSOGOutOfStockSkuData dbEntity = new VSOGOutOfStockSkuData(); // 复制其他字段,比如skuId、stockStatus这些... dbEntity.setSkuId(fileModel.getSkuId()); dbEntity.setStockStatus(fileModel.getStockStatus()); // 处理日期转换 if (fileModel.getPlaceDate() != null && !fileModel.getPlaceDate().isBlank()) { LocalDate localDate = LocalDate.parse(fileModel.getPlaceDate(), DATE_FORMATTER); dbEntity.setPlaceDate(java.sql.Date.valueOf(localDate)); } return dbEntity; } }
然后在你的步骤配置里把这个处理器加上就行,确保数据在写入数据库前完成转换。
方法2:自定义Spring转换器,让框架自动处理
如果不想在处理器里写硬编码的转换逻辑,可以自定义一个字符串转java.sql.Date的转换器,注册到Spring的ConversionService里,这样框架会自动帮你完成绑定:
第一步:写转换器类
@Component public class StringToSqlDateConverter implements Converter<String, java.sql.Date> { private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @Override public java.sql.Date convert(String dateStr) { if (dateStr == null || dateStr.isBlank()) { return null; } LocalDate localDate = LocalDate.parse(dateStr, DATE_FORMATTER); return java.sql.Date.valueOf(localDate); } }
第二步:注册转换器到ConversionService
在你的Batch配置类里,把这个转换器加入到默认的转换服务中,然后配置给FieldSetMapper:
@Configuration public class BatchStepConfig { @Autowired private StringToSqlDateConverter dateConverter; @Bean public ConversionService batchConversionService() { DefaultConversionService conversionService = new DefaultConversionService(); conversionService.addConverter(dateConverter); return conversionService; } // 配置FlatFileItemReader的时候,把转换服务设置给BeanWrapperFieldSetMapper @Bean public FlatFileItemReader<VSOGOutOfStockSkuDataForBatchJob> skuFileReader() { FlatFileItemReader<VSOGOutOfStockSkuDataForBatchJob> reader = new FlatFileItemReader<>(); // 配置文件路径、分隔符等... reader.setResource(new FileSystemResource("your-local-file-path")); reader.setLineTokenizer(new DelimitedLineTokenizer() {{ setNames("skuId", "placeDate", "stockStatus"); // 对应文件里的字段名 }}); // 设置带自定义转换服务的FieldSetMapper BeanWrapperFieldSetMapper<VSOGOutOfStockSkuDataForBatchJob> fieldSetMapper = new BeanWrapperFieldSetMapper<>(); fieldSetMapper.setTargetType(VSOGOutOfStockSkuDataForBatchJob.class); fieldSetMapper.setConversionService(batchConversionService()); reader.setLineMapper(new DefaultLineMapper<>() {{ setLineTokenizer(reader.getLineTokenizer()); setFieldSetMapper(fieldSetMapper); }}); return reader; } }
这样配置后,Spring Batch在读取文件映射到模型类的时候,或者从模型转实体的时候,都会自动用咱们的转换器处理日期字段。
方法3:调整实体类字段类型(可选)
如果你的项目允许修改数据库实体类的字段类型,可以把java.sql.Date改成java.time.LocalDate(Java 8+推荐的日期类型),这样和文件里的字符串日期适配性更好,Spring也能自动处理转换(只要格式匹配)。修改后的数据库实体类字段:
@Entity public class VSOGOutOfStockSkuData { // 其他字段... private LocalDate placeDate; // getter和setter... }
对应的文件模型类也可以改成LocalDate类型,这样就不用额外写转换逻辑了,不过这个方法需要确保数据库字段也支持LocalDate(比如MySQL的DATE类型是兼容的)。
内容的提问来源于stack exchange,提问作者Sanjay Naik

