NoSuchMethodException:java.time.LocalDateTime。<init>()使用Super CSV读取CSV

时间:2016-12-09 22:37:03

标签: java csv java-8 dozer supercsv

我使用Super CSV's LocalDateTime编写了一个仅包含ICsvDozerBeanWriter CSV文件的实体,并在使用ICsvDozerBeanReader阅读时遇到错误。我能够成功读取和写入Date对象,但LocalDateTime无法正常工作。

我添加了super-csv-java8依赖项,写作部分似乎工作正常。

我已经创建了一个小型演示应用程序in this Github repo来复制问题。运行main()方法,错误将输出到控制台。

这是我得到的例外:

2016-12-09 22:24:02.427 ERROR 50405 --- [           main] org.dozer.MappingProcessor               : Field mapping error -->
  MapId: null
  Type: null
  Source parent class: org.supercsv.io.dozer.CsvDozerBeanData
  Source field name: columns
  Source field type: class java.time.LocalDateTime
  Source field value: 2016-12-09T22:24:02.226
  Dest parent class: com.example.Entity
  Dest field name: dateTime
  Dest field type: java.time.LocalDateTime

org.dozer.MappingException: java.lang.NoSuchMethodException: java.time.LocalDateTime.<init>()
    at org.dozer.util.MappingUtils.throwMappingException(MappingUtils.java:82) ~[dozer-5.4.0.jar:na]
    at org.dozer.factory.ConstructionStrategies$ByConstructor.newInstance(ConstructionStrategies.java:261) ~[dozer-5.4.0.jar:na]
    at org.dozer.factory.ConstructionStrategies$ByConstructor.create(ConstructionStrategies.java:245) ~[dozer-5.4.0.jar:na]
    at org.dozer.factory.DestBeanCreator.create(DestBeanCreator.java:65) ~[dozer-5.4.0.jar:na]
    at org.dozer.MappingProcessor.mapCustomObject(MappingProcessor.java:489) [dozer-5.4.0.jar:na]
    at org.dozer.MappingProcessor.mapOrRecurseObject(MappingProcessor.java:446) [dozer-5.4.0.jar:na]
    at org.dozer.MappingProcessor.mapFromFieldMap(MappingProcessor.java:342) [dozer-5.4.0.jar:na]
    at org.dozer.MappingProcessor.mapField(MappingProcessor.java:288) [dozer-5.4.0.jar:na]
    at org.dozer.MappingProcessor.map(MappingProcessor.java:248) [dozer-5.4.0.jar:na]
    at org.dozer.MappingProcessor.map(MappingProcessor.java:197) [dozer-5.4.0.jar:na]
    at org.dozer.MappingProcessor.map(MappingProcessor.java:187) [dozer-5.4.0.jar:na]
    at org.dozer.MappingProcessor.map(MappingProcessor.java:124) [dozer-5.4.0.jar:na]
    at org.dozer.MappingProcessor.map(MappingProcessor.java:119) [dozer-5.4.0.jar:na]
    at org.dozer.DozerBeanMapper.map(DozerBeanMapper.java:120) [dozer-5.4.0.jar:na]
    at org.supercsv.io.dozer.CsvDozerBeanReader.readIntoBean(CsvDozerBeanReader.java:220) [super-csv-dozer-2.4.0.jar:na]
    at org.supercsv.io.dozer.CsvDozerBeanReader.read(CsvDozerBeanReader.java:160) [super-csv-dozer-2.4.0.jar:na]
    at com.example.DemoApplication.readEntities(DemoApplication.java:51) [classes/:na]
    at com.example.DemoApplication.main(DemoApplication.java:39) [classes/:na]
Caused by: java.lang.NoSuchMethodException: java.time.LocalDateTime.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082) ~[na:1.8.0_66]
    at java.lang.Class.getDeclaredConstructor(Class.java:2178) ~[na:1.8.0_66]
    at org.dozer.factory.ConstructionStrategies$ByConstructor.newInstance(ConstructionStrategies.java:257) ~[dozer-5.4.0.jar:na]
    ... 16 common frames omitted

org.dozer.MappingException: java.lang.NoSuchMethodException: java.time.LocalDateTime.<init>()
    at org.dozer.util.MappingUtils.throwMappingException(MappingUtils.java:82)
    at org.dozer.factory.ConstructionStrategies$ByConstructor.newInstance(ConstructionStrategies.java:261)
    at org.dozer.factory.ConstructionStrategies$ByConstructor.create(ConstructionStrategies.java:245)
    at org.dozer.factory.DestBeanCreator.create(DestBeanCreator.java:65)
    at org.dozer.MappingProcessor.mapCustomObject(MappingProcessor.java:489)
    at org.dozer.MappingProcessor.mapOrRecurseObject(MappingProcessor.java:446)
    at org.dozer.MappingProcessor.mapFromFieldMap(MappingProcessor.java:342)
    at org.dozer.MappingProcessor.mapField(MappingProcessor.java:288)
    at org.dozer.MappingProcessor.map(MappingProcessor.java:248)
    at org.dozer.MappingProcessor.map(MappingProcessor.java:197)
    at org.dozer.MappingProcessor.map(MappingProcessor.java:187)
    at org.dozer.MappingProcessor.map(MappingProcessor.java:124)
    at org.dozer.MappingProcessor.map(MappingProcessor.java:119)
    at org.dozer.DozerBeanMapper.map(DozerBeanMapper.java:120)
    at org.supercsv.io.dozer.CsvDozerBeanReader.readIntoBean(CsvDozerBeanReader.java:220)
    at org.supercsv.io.dozer.CsvDozerBeanReader.read(CsvDozerBeanReader.java:160)
    at com.example.DemoApplication.readEntities(DemoApplication.java:51)
    at com.example.DemoApplication.main(DemoApplication.java:39)
Caused by: java.lang.NoSuchMethodException: java.time.LocalDateTime.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.getDeclaredConstructor(Class.java:2178)
    at org.dozer.factory.ConstructionStrategies$ByConstructor.newInstance(ConstructionStrategies.java:257)

理想情况下,我想以yyyy-MM-dd格式将日期写入CSV文件,但一次一步!

3 个答案:

答案 0 :(得分:5)

虽然Super CSV 支持通过ParseLocalDateTimeFmtLocalDateTime单元处理器(java.time.LocalDateTime模块中提供)super-csv-java8来读写LocalDateTime ,Dozer试图实例化目标CsvDozerBeanReader对象,而不是使用单元处理器的结果(它是带有Dozer的known issue - 它不支持Java 8时间)。

2个解决方法是......

使用CsvBeanReader

CsvBeanReader交换<dependency> <groupId>io.craftsman</groupId> <artifactId>dozer-jdk8-support</artifactId> <version>1.0.2</version> </dependency> 。你将失去深度/索引映射支持,但从好的方面来说它会快得多。

在DozerBeanMapper中配置Java 8支持

正如推土机问题所讨论的那样,有一个dozer-jdk8-support库可以解决这个问题。

添加依赖项:

DozerBeanMapper

配置DozerBeanMapper beanMapper = new DozerBeanMapper(); beanMapper.setMappingFiles(Collections.singletonList("dozerJdk8Converters.xml"));

CsvDozerBeanReader

并将其提供给new CsvDozerBeanReader(reader, CsvPreference.STANDARD_PREFERENCE, beanMapper)

  from scipy.stats import uniform
  uniform.expect(lambda k: k**2,lb=-0.2,ub=0.2)

这是一个样板,但如果你真的需要Dozer支持,这将让你开始运行。

P.S。我创建了一个PR来更新documentation - 只列出了一个Java 8单元处理器,并且有很多!

答案 1 :(得分:2)

LocalDateTime是一个不可变对象,并且: 如果没有附加信息(如偏移或时区),它就不能代表时间线上的瞬间。

来源:https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html

因此,您正尝试重新构建一个无法首先实例化的实例。

可能的解决方案:为什么不保存所需日期的字符串表示形式,然后将其解析回LocalDateTime?

答案 2 :(得分:1)

LocalDateTime 片刻

Answer by moldovean是正确的。 LocalDateTime是用于某个时间点的错误类。没有时区概念或从UTC偏移,这个类只是对可能时刻的模糊概念。 没有实际意义,直到您应用时区或偏移量。

自定义单元处理器

我不是SuperCSV的专家。我找不到完整的文档来讨论它自动处理的数据类型。如果尚未更新此库以直接处理java.time类型,则需要编写自己的映射实现,显然是custom cell processor

查看this list of built-in cell processors,似乎确实尚未针对java.time类型更新库。

我在your example app中看不到任何地图或自定义单元格处理器。

Instant

要表示时刻,时间轴上的一个点,请使用Instant类。

Instant类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。

Instant instant = Instant.now();  // Current moment in UTC.

ISO 8601

ISO 8601标准定义了许多日期时间值的格式,这些格式被序列化为文本。对于不同文化的人来说,这些都是实用的,明确的,易于解析和直观的。

java.time类在解析/生成字符串时默认使用这些格式。这包括Instant类。

String output = instant.toString();
  

2016-12-09T22:27:17.783Z

Instant instant = Instant.parse( "2016-12-09T22:27:17.783Z" );

除了OffsetDateTime之外,您还可以从ZonedDateTime班级和Instant班级生成字符串。它们也可以使用ISO 8601为双向数据交换生成双字符串。在ZonedDateTime的情况下,toString方法通过在方括号中明智地附加时区名称来扩展ISO 8601格式。但通常最好使用UTC(Instant)值。