Spring 启动 opencsv
Spring Boot opencsv
我正在尝试使用 opencsv 来解析这样的 csv 文件:
name,purchase,date
TEST,TEST,2020-10-20T00:37:53.562000000Z
TEST,TEST,2020-10-20T00:37:53.562000000Z
我正尝试按照本教程将解析后的数据添加到 firebase 数据库:https://attacomsian.com/blog/spring-boot-upload-parse-csv-file。这是我的 class 数据:
public class Records {
@CsvBindByName
private String name;
@CsvBindByName
private String purchase;
@CsvBindByName
private Timestamp date;
// get and setters left out for brevity pls comment if needed
}
当我解析文件时出现此错误:
Exception in thread "pool-6-thread-2" Exception in thread "pool-6-thread-1" Exception in thread "pool-6-thread-4" Exception in thread "pool-6-thread-3" java.lang.RuntimeException: com.opencsv.exceptions.CsvDataTypeMismatchException: Conversion of 2022-10-20T00:37:53.562000000Z to com.google.cloud.Timestamp failed.
at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:99)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.opencsv.exceptions.CsvDataTypeMismatchException: Conversion of 2022-10-20T00:37:53.562000000Z to com.google.cloud.Timestamp failed.
at com.opencsv.bean.ConverterPrimitiveTypes.convertToRead(ConverterPrimitiveTypes.java:128)
at com.opencsv.bean.BeanFieldSingleValue.convert(BeanFieldSingleValue.java:98)
at com.opencsv.bean.AbstractBeanField.setFieldValue(AbstractBeanField.java:180)
at com.opencsv.bean.AbstractMappingStrategy.setFieldValue(AbstractMappingStrategy.java:581)
at com.opencsv.bean.AbstractMappingStrategy.populateNewBean(AbstractMappingStrategy.java:328)
at com.opencsv.bean.concurrent.ProcessCsvLine.processLine(ProcessCsvLine.java:128)
at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:83)
... 3 more
Caused by: org.apache.commons.beanutils.ConversionException: Can't convert value '2022-10-20T00:37:53.562000000Z' to type class com.google.cloud.Timestamp
at org.apache.commons.beanutils.converters.AbstractConverter.conversionException(AbstractConverter.java:474)
at org.apache.commons.beanutils.converters.StringConverter.convertToType(StringConverter.java:96)
at org.apache.commons.beanutils.converters.AbstractConverter.convert(AbstractConverter.java:169)
at org.apache.commons.beanutils.converters.ConverterFacade.convert(ConverterFacade.java:61)
at org.apache.commons.beanutils.ConvertUtilsBean.convert(ConvertUtilsBean.java:491)
at com.opencsv.bean.ConverterPrimitiveTypes.convertToRead(ConverterPrimitiveTypes.java:118)
... 9 more
我该如何解决这个错误?我需要更改日期列的格式吗?我从数据库中的记录中复制了日期格式,这样格式就是它应该如何存储在数据库中
在这种情况下,您可以尝试将 Timestamp to Date 替换掉吗?
像这样:
@CsvBindByName private Date date;
时间戳字段对象是 com.google.cloud.Timestamp
包中的一个实例。
正如@Allen 所建议的,您可能需要研究 java.util.date
或更好的事件,Java 8 次 API java.time.LocalTime
以获得 ConverterPrimitiveTypes
的支持自动转换。
我将 csv 格式更改为:
name,purchase,date
TEST,TEST,2018-09-16T08:00:00
TEST,TEST,2018-09-16T08:00:00
我将绑定到 csv 的 class 修改为如下所示:
public class CsvRecords {
@CsvBindByName
private String name;
@CsvBindByName
private String purchase;
@CsvBindByName
private String date;
// get and setters left out for brevity pls comment if needed
}
数据库中数据的 POJO class:
public class Records {
private String name;
private String purchase;
private Timestamp date;
// get and setters left out for brevity pls comment if needed
}
在控制器中上传时 class 然后我将字符串转换为 LocalDateTime,然后再次转换为 Timestamp,如下所示:
@PostMapping("/upload-csv-file")
public String uploadCSVFile(@RequestParam("file") MultipartFile file, Model model) {
// validate file
if (file.isEmpty()) {
model.addAttribute("message", "Please select a CSV file to upload.");
model.addAttribute("status", false);
} else {
// parse CSV file to create a list of `User` objects
try (Reader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
// create csv bean reader
CsvToBean<Records> csvToBean = new CsvToBeanBuilder(reader)
.withType(Records.class)
.withIgnoreLeadingWhiteSpace(true)
.build();
// convert `CsvToBean` object to list of records
List<Records> records = csvToBean.parse();
// save users in DB?
for(int i = 0; i<records.size(); i++){
LocalDateTime localDateTime = LocalDateTime.parse(records.get(i).getDate);
Timestamp timestamp = Timestamp.valueOf(localDateTime);
Records rec = new Records(records.get(i).getName(), records.get(i).getPurchase(), timestamp)
firebaseServices.saveDetails(rec);
}
} catch (Exception ex) {
model.addAttribute("message", "An error occurred while processing the CSV file.");
model.addAttribute("status", false);
}
}
return "file-upload-status";
}
有关 firebaseServices class(saveDetails 方法)实现的详细信息,我使用了此 tutorial
我正在尝试使用 opencsv 来解析这样的 csv 文件:
name,purchase,date
TEST,TEST,2020-10-20T00:37:53.562000000Z
TEST,TEST,2020-10-20T00:37:53.562000000Z
我正尝试按照本教程将解析后的数据添加到 firebase 数据库:https://attacomsian.com/blog/spring-boot-upload-parse-csv-file。这是我的 class 数据:
public class Records {
@CsvBindByName
private String name;
@CsvBindByName
private String purchase;
@CsvBindByName
private Timestamp date;
// get and setters left out for brevity pls comment if needed
}
当我解析文件时出现此错误:
Exception in thread "pool-6-thread-2" Exception in thread "pool-6-thread-1" Exception in thread "pool-6-thread-4" Exception in thread "pool-6-thread-3" java.lang.RuntimeException: com.opencsv.exceptions.CsvDataTypeMismatchException: Conversion of 2022-10-20T00:37:53.562000000Z to com.google.cloud.Timestamp failed.
at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:99)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.opencsv.exceptions.CsvDataTypeMismatchException: Conversion of 2022-10-20T00:37:53.562000000Z to com.google.cloud.Timestamp failed.
at com.opencsv.bean.ConverterPrimitiveTypes.convertToRead(ConverterPrimitiveTypes.java:128)
at com.opencsv.bean.BeanFieldSingleValue.convert(BeanFieldSingleValue.java:98)
at com.opencsv.bean.AbstractBeanField.setFieldValue(AbstractBeanField.java:180)
at com.opencsv.bean.AbstractMappingStrategy.setFieldValue(AbstractMappingStrategy.java:581)
at com.opencsv.bean.AbstractMappingStrategy.populateNewBean(AbstractMappingStrategy.java:328)
at com.opencsv.bean.concurrent.ProcessCsvLine.processLine(ProcessCsvLine.java:128)
at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:83)
... 3 more
Caused by: org.apache.commons.beanutils.ConversionException: Can't convert value '2022-10-20T00:37:53.562000000Z' to type class com.google.cloud.Timestamp
at org.apache.commons.beanutils.converters.AbstractConverter.conversionException(AbstractConverter.java:474)
at org.apache.commons.beanutils.converters.StringConverter.convertToType(StringConverter.java:96)
at org.apache.commons.beanutils.converters.AbstractConverter.convert(AbstractConverter.java:169)
at org.apache.commons.beanutils.converters.ConverterFacade.convert(ConverterFacade.java:61)
at org.apache.commons.beanutils.ConvertUtilsBean.convert(ConvertUtilsBean.java:491)
at com.opencsv.bean.ConverterPrimitiveTypes.convertToRead(ConverterPrimitiveTypes.java:118)
... 9 more
我该如何解决这个错误?我需要更改日期列的格式吗?我从数据库中的记录中复制了日期格式,这样格式就是它应该如何存储在数据库中
在这种情况下,您可以尝试将 Timestamp to Date 替换掉吗? 像这样:
@CsvBindByName private Date date;
时间戳字段对象是 com.google.cloud.Timestamp
包中的一个实例。
正如@Allen 所建议的,您可能需要研究 java.util.date
或更好的事件,Java 8 次 API java.time.LocalTime
以获得 ConverterPrimitiveTypes
的支持自动转换。
我将 csv 格式更改为:
name,purchase,date
TEST,TEST,2018-09-16T08:00:00
TEST,TEST,2018-09-16T08:00:00
我将绑定到 csv 的 class 修改为如下所示:
public class CsvRecords {
@CsvBindByName
private String name;
@CsvBindByName
private String purchase;
@CsvBindByName
private String date;
// get and setters left out for brevity pls comment if needed
}
数据库中数据的 POJO class:
public class Records {
private String name;
private String purchase;
private Timestamp date;
// get and setters left out for brevity pls comment if needed
}
在控制器中上传时 class 然后我将字符串转换为 LocalDateTime,然后再次转换为 Timestamp,如下所示:
@PostMapping("/upload-csv-file")
public String uploadCSVFile(@RequestParam("file") MultipartFile file, Model model) {
// validate file
if (file.isEmpty()) {
model.addAttribute("message", "Please select a CSV file to upload.");
model.addAttribute("status", false);
} else {
// parse CSV file to create a list of `User` objects
try (Reader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
// create csv bean reader
CsvToBean<Records> csvToBean = new CsvToBeanBuilder(reader)
.withType(Records.class)
.withIgnoreLeadingWhiteSpace(true)
.build();
// convert `CsvToBean` object to list of records
List<Records> records = csvToBean.parse();
// save users in DB?
for(int i = 0; i<records.size(); i++){
LocalDateTime localDateTime = LocalDateTime.parse(records.get(i).getDate);
Timestamp timestamp = Timestamp.valueOf(localDateTime);
Records rec = new Records(records.get(i).getName(), records.get(i).getPurchase(), timestamp)
firebaseServices.saveDetails(rec);
}
} catch (Exception ex) {
model.addAttribute("message", "An error occurred while processing the CSV file.");
model.addAttribute("status", false);
}
}
return "file-upload-status";
}
有关 firebaseServices class(saveDetails 方法)实现的详细信息,我使用了此 tutorial