Gagal mengonversi nilai properti jenis 'java.lang.String' menjadi jenis 'java.sql.Date' yang diperlukan
Saya telah menulis pekerjaan batch musim semi yang membaca CSV dan menulis ke SQL server db. File CSV memiliki beberapa bidang tipe Datedan TimeStamp. Saya menggunakan FlatFileItemReader dan JdbcBatchItemWriter.
Format Tanggal di CSV saya adalah yyyy-MM-dd dan format TimeStamp adalah yyyy-MM-hh HH: mm: ss.SSSSSS
CATATAN: Saya menggunakan java.sql.Date dan TimeStamp, BUKAN java.util.Date dan TimeStamp
Kelas pengguna:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User{
private String firstName;
private String lastName;
private Date dateOfBirth;
private Date dateOfJoining;
private TimeStamp timeStampReg;
...
Saya menggunakan kelas model yang sama Useruntuk membaca dari DB pada langkah yang berbeda.
Pembaca di Kelas Konfigurasi terlihat seperti:
@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;
}
...
Saat menjalankan pekerjaan, saya mendapatkan kesalahan:
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]
Ini memberikan kesalahan yang sama untuk bidang tanggal dan stempel waktu lainnya ( dateOfJoiningdan timeStampReg)
EDIT:
Saya menyelesaikan kesalahan untuk Datebidang jenis dengan solusi berikut, Tapi saya masih mendapatkan kesalahan yang sama untuk TimeStampbidang jenis.
Saya membuat custom BeanWrapperFieldSetMapperdan menimpanya initBinderuntuk menambahkan 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);
}
}
dan gunakan objeknya alih-alih objek aktual BeanWrapperFieldSetMapperdi dalam flatFileItemReaderkacang dengan menggantinya dengan:
MyCustomBeanWrapperFieldSetMapper<User> fieldSetMapper = new MyCustomBeanWrapperFieldSetMapper<>();
PS: Editor Kustom tidak berfungsi untuk java.sql.Datedan java.sql.TimeStamp. Jadi saya harus Beralih ke java.util.Date. Itu menyelesaikannya untuk Datetipe tetapi kesalahan masih berlanjut untuk TimeStamptipe.
Jawaban
Kedengarannya seolah-olah kumpulan Anda hanya dapat membagi baris Anda menjadi Stringnilai, tetapi gagal mengonversi jenis yang lebih eksotis. The javadoc untukBeanWrapperFieldSetMapper mengatakan:
Untuk menyesuaikan cara nilai FieldSet diubah ke jenis yang diinginkan untuk dimasukkan ke dalam prototipe, ada beberapa pilihan. Anda dapat memasukkan instance PropertyEditor langsung melalui properti customEditors, atau Anda dapat mengganti metode createBinder (Object) dan initBinder (DataBinder), atau Anda dapat menyediakan implementasi FieldSet kustom. Anda juga dapat menggunakan ConversionService untuk mengonversi ke jenis yang diinginkan melalui properti conversionService.
Saya sarankan untuk bereksperimen dengan beberapa alternatif tersebut berdasarkan mana yang paling sesuai dengan kebutuhan Anda.
EDIT: Solusi yang mungkin adalah dengan hanya menggunakan ApplicationConversionServicekelas, yang disediakan Spring Boot di luar kotak. Saya membuat contoh kerja di GitHub jika Anda ingin melihat solusi saya dan, yang lebih penting, asumsi saya tentang proyek Anda. Perhatikan bahwa saya menggunakan java.sql.*kelas dalam proyek contoh saya karena ApplicationConversionServicetampaknya berfungsi dengan baik dengan itu.
@Bean
FieldSetMapper<User> fieldSetMapper() {
BeanWrapperFieldSetMapper<User> fieldSetMapper = new BeanWrapperFieldSetMapper<>();
fieldSetMapper.setTargetType(User.class);
fieldSetMapper.setConversionService(ApplicationConversionService.getSharedInstance());
return fieldSetMapper;
}