'Java.lang.String' türünün özellik değeri gerekli 'java.sql.Date' türüne dönüştürülemedi

Oct 08 2020

Bir CSV okuyan ve SQL sunucu veritabanına yazan bir yaylı toplu iş yazdım. CSV dosyasında bazı tür alanları Dateve TimeStamp. FlatFileItemReader ve JdbcBatchItemWriter kullanıyorum.

CSV'mdeki Tarih biçimi yyyy-MM-gg ve TimeStamp biçimi yyyy-MM-gg SS: mm: ss.SSSSS'dir.

NOT: java.sql.Date ve TimeStamp kullanıyorum, java.util.Date ve TimeStamp DEĞİL

Kullanıcı sınıfı:

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

UserDB'den farklı bir adımda okumak için aynı model sınıfını kullanıyorum.

Yapılandırma Sınıfındaki Okuyucu şuna benzer:

@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;
    }
...

İşi çalıştırırken şu hataları alıyorum:

Parsing error at line: 1 in resource=Path to the CSV file

Failed to convert property value of type 'java.lang.String' to required type 'java.sql.Date' for property 'dateOfBirth';

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]

Diğer tarih ve zaman damgası alanları için aynı hatayı veriyor ( dateOfJoiningve timeStampReg)

DÜZENLE:

DateTür alanları için hatayı aşağıdaki çözümle çözdüm, ancak yine de TimeStamptür alanı için aynı hatayı alıyorum .

Bir oluşturdum custom BeanWrapperFieldSetMapperve initBinderbir eklemek için onun üzerine yazdım 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);
        
    }
}

ve çekirdekteki gerçek yerine nesnesini BeanWrapperFieldSetMapperşu şekilde flatFileItemReaderdeğiştirerek kullanın:

MyCustomBeanWrapperFieldSetMapper<User> fieldSetMapper = new MyCustomBeanWrapperFieldSetMapper<>();

Not: Özel Düzenleyici java.sql.Dateve için çalışmadı java.sql.TimeStamp. Bu yüzden geçiş yapmak zorunda kaldım java.util.Date. Bu, Datetür için çözdü, ancak hata hala yazım için devam ediyor TimeStamp.

Yanıtlar

2 ThomasKåsene Oct 08 2020 at 21:27

Grubunuz yalnızca satırlarınızı Stringdeğerlere bölebilir , ancak daha egzotik türleri dönüştüremiyormuş gibi geliyor. İçin javadocBeanWrapperFieldSetMapper diyor:

FieldSet değerlerinin prototipe enjekte edilmek üzere istenen türe dönüştürülme şeklini özelleştirmek için birkaç seçenek vardır. PropertyEditor örneklerini doğrudan customEditors özelliği aracılığıyla enjekte edebilir veya createBinder (Object) ve initBinder (DataBinder) yöntemlerini geçersiz kılabilir veya özel bir FieldSet uygulaması sağlayabilirsiniz. Ayrıca, conversionService özelliği aracılığıyla istenen türe dönüştürmek için bir ConversionService kullanabilirsiniz.

İhtiyacınıza en uygun olanları temel alarak bu alternatiflerden bazılarını denemenizi öneririm.

DÜZENLEME: Olası bir çözüm, ApplicationConversionServiceSpring Boot'un kutudan çıkar çıkardığı sınıfı kullanmak olabilir . Ben kurmak GitHub üzerinde çalışma örneği benim çözümü ve daha da önemlisi bir göz atın isterseniz, projeniz hakkında benim varsayımlar. java.sql.*Örnek projemdeki sınıfları kullanıyorum çünkü ApplicationConversionServicegörünüşe göre bunlarla iyi çalışıyor.

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