无法将“java.lang.String"类型的属性值转换为所需类型“java.sql.Date" [英] Failed to convert property value of type 'java.lang.String' to required type 'java.sql.Date'

查看:26
本文介绍了无法将“java.lang.String"类型的属性值转换为所需类型“java.sql.Date"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个 Spring 批处理作业,它读取 CSV 并写入 SQL 服务器数据库.CSV 文件有一些DateTimeStamp 类型的字段.我正在使用 FlatFileItemReader 和 JdbcBatchItemWriter.

I've written a spring batch job that reads a CSV and writes into SQL server db. The CSV file has some fields of type Date and TimeStamp. I'm using FlatFileItemReader and JdbcBatchItemWriter.

我的 CSV 中的日期格式是 yyyy-MM-dd时间戳格式为 yyyy-MM-dd HH:mm:ss.SSSSSS

The Date format in my CSV is yyyy-MM-dd and the TimeStamp format is yyyy-MM-dd HH:mm:ss.SSSSSS

注意:我使用的是 java.sql.Date 和 TimeStamp,而不是 java.util.Date 和 TimeStamp

用户类别:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User{
    private String firstName;
    private String lastName;
    private Date dateOfBirth;
    private Date dateOfJoining;
    private TimeStamp timeStampReg;
...

我使用相同的模型类 User 在不同的步骤中从数据库中读取数据.

I use the same model class User to read from the DB in a different step.

配置类中的阅读器如下所示:

The Reader in Configuration Class looks like:

@Configuration
public class BatchConfigClass{

    
    //Step 1
    @Bean
    public FlatFileItemReader<User> itemReader() {

        FlatFileItemReader<User> flatFileItemReader = new FlatFileItemReader<>();
        flatFileItemReader.setResource(inputResource);
        flatFileItemReader.setName("CSV-Reader");
        flatFileItemReader.setLineMapper(lineMapper());
        return flatFileItemReader;
    }

    @Bean
    public LineMapper<User> lineMapper() {

        DefaultLineMapper<User> defaultLineMapper = new DefaultLineMapper<>();
        DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();

        lineTokenizer.setDelimiter(",");
        lineTokenizer.setStrict(false);
        lineTokenizer.setNames(new String[]{"firstName", "lastName", "dateOfBirth", "dateOfJoining","timeStampReg"});

        BeanWrapperFieldSetMapper<User> fieldSetMapper = new BeanWrapperFieldSetMapper<>();
        fieldSetMapper.setTargetType(User.class);           

        defaultLineMapper.setLineTokenizer(lineTokenizer);
        defaultLineMapper.setFieldSetMapper(fieldSetMapper);

        return defaultLineMapper;
    }
...

在运行作业时,出现错误:

On running the job, I get the errors:

在行解析错误:1 in resource=Path to the CSV file

未能将java.lang.String"类型的属性值转换为属性dateOfBirth"所需的类型java.sql.Date";

Field error in object 'target' on field 'dateOfBirth': rejected value [1998-12-31]; codes [typeMismatch.target.dateOfBirth,typeMismatch.dateOfBirth,typeMismatch.java.sql.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [target.dateOfBirth,dateOfBirth]; arguments []; default message [dateOfBirth]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.sql.Date' for property 'dateOfBirth'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.sql.Date' for property 'dateOfBirth': no matching editors or conversion strategy found]

它为其他日期和时间戳字段(dateOfJoiningtimeStampReg)提供了相同的错误

It gives the same error for other date and timestamp fields(dateOfJoining and timeStampReg)

我通过以下解决方案解决了 Date 类型字段的错误,但对于 TimeStamp 类型字段,我仍然遇到相同的错误.

I resolved the error for the Date type fields by the following solution, But I'm still getting the same error for TimeStamp type field.

我创建了一个 custom BeanWrapperFieldSetMapper 并覆盖它的 initBinder 以添加一个 CustomDateEditor.

I created a custom BeanWrapperFieldSetMapper and override its initBinder to add a CustomDateEditor.

public class MyCustomBeanWrapperFieldSetMapper<User> extends BeanWrapperFieldSetMapper<FSMChequePayment> {

    @Override
    protected void initBinder(DataBinder binder) {
        CustomDateEditor editor = new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true);
        binder.registerCustomEditor(Date.class, editor);

        CustomDateEditor editorTimeStamp = new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS"), true);
        binder.registerCustomEditor(TimeStamp.class,editorTimeStamp);
        
    }
}

并使用它的对象代替 flatFileItemReader bean 中实际的 BeanWrapperFieldSetMapper,将其替换为:

and use its object instead of the actual BeanWrapperFieldSetMapperin the flatFileItemReader bean by replacing it with:

MyCustomBeanWrapperFieldSetMapper<用户>fieldSetMapper = new MyCustomBeanWrapperFieldSetMapper<>();

PS:自定义编辑器不适用于 java.sql.Datejava.sql.TimeStamp.所以我不得不切换到 java.util.Date.这解决了 Date 类型的问题,但 TimeStamp 类型的错误仍然存​​在.

PS: The Custom Editor didn't work for java.sql.Date and java.sql.TimeStamp. So I had to Switch to java.util.Date. That resolved it for Date type but the error still persists for TimeStamp type.

推荐答案

听起来好像您的批处理只能将您的行拆分为 String 值,但无法转换更奇特的类型.JavaDoc对于 BeanWrapperFieldSetMapper 说:

It sounds as though your batch is only able to split your lines into String values, but fails to convert the more exotic types. The JavaDoc for BeanWrapperFieldSetMapper says:

要自定义将 FieldSet 值转换为所需类型以注入原型的方式,有多种选择.您可以直接通过 customEditors 属性注入 PropertyEditor 实例,或者您可以覆盖 createBinder(Object) 和 initBinder(DataBinder) 方法,或者您可以提供自定义 FieldSet 实现.您还可以使用 ConversionService 通过 conversionService 属性转换为所需的类型.

To customize the way that FieldSet values are converted to the desired type for injecting into the prototype there are several choices. You can inject PropertyEditor instances directly through the customEditors property, or you can override the createBinder(Object) and initBinder(DataBinder) methods, or you can provide a custom FieldSet implementation. You can also use a ConversionService to convert to the desired type through the conversionService property.

我建议根据哪些替代方案最适合您的需要,尝试其中的一些替代方案.

I suggest experimenting with some of those alternatives based on which ones fit your need best.

一个可能的解决方案是简单地使用 ApplicationConversionService 类,它是 Spring Boot 开箱即用的.如果你想看看我的解决方案,我在 GitHub 上设置了一个 工作示例更重要的是,我对你的项目的假设.请注意,我在示例项目中使用了 java.sql.* 类,因为 ApplicationConversionService 似乎可以很好地处理这些类.

A possible solution can be to simply use the ApplicationConversionService class, which Spring Boot provides out of the box. I set up a working example on GitHub if you want to take a look at my solution and, more importantly, my assumptions about your project. Note that I'm using the java.sql.* classes in my example project because the ApplicationConversionService works fine with those, seemingly.

@Bean
FieldSetMapper<User> fieldSetMapper() {
    BeanWrapperFieldSetMapper<User> fieldSetMapper = new BeanWrapperFieldSetMapper<>();
    fieldSetMapper.setTargetType(User.class);
    fieldSetMapper.setConversionService(ApplicationConversionService.getSharedInstance());
    return fieldSetMapper;
}

这篇关于无法将“java.lang.String"类型的属性值转换为所需类型“java.sql.Date"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆