Spring-Data-MongoDB: 使用自定义转换器升级到 2.0.7 后无法从类型转换
Spring-Data-MongoDB: Failed to convert from type after upgrade to 2.0.7 with custom converter
我今天刚刚升级到 Spring Boot 2.0.2,作为升级的一部分,我还升级到了 Spring-Data-MongoDB 2.0.7.
我有以下实体:
@Document
@Data
public class User {
private String username;
private String password;
private List<String> authorities;
public User(String username, String password, List<String> authorities) {
this.username = username;
this.password = password;
this.authorities = authorities;
}
}
在我的测试中,我使用以下方法插入了一个新用户:
mongoTemplate.save(new User("testuser", "a$OuKj.lXzPxlwgr2Jy28E4ehHuxnVZ7BuL46qX9fd6vAijcDN6UeHe", Collections.singletonList("user")));
这在使用 Spring Boot 2.0.1(分别为 Spring-Data-MongoDB 2.0.6)时完美运行。使用升级后的 Spring-Data-MongoDB 版本,出现以下错误:
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.ZonedDateTime] for value 'testuser'; nested exception is java.time.format.DateTimeParseException: Text 'testuser' could not be parsed at index 0
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:46)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:191)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getPotentiallyConvertedSimpleWrite(MappingMongoConverter.java:849)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeSimpleInternal(MappingMongoConverter.java:829)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeProperties(MappingMongoConverter.java:488)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:462)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:436)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.write(MappingMongoConverter.java:391)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.write(MappingMongoConverter.java:86)
at org.springframework.data.mongodb.core.MongoTemplate.toDocument(MongoTemplate.java:1070)
at org.springframework.data.mongodb.core.MongoTemplate.doSave(MongoTemplate.java:1253)
at org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:1201)
at org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:1185)
....
Caused by: java.time.format.DateTimeParseException: Text 'testuser' could not be parsed at index 0
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
at java.time.ZonedDateTime.parse(ZonedDateTime.java:597)
at at.riag.scanpay.config.MongoConfig$StringToZonedDateTime.convert(MongoConfig.java:34)
at at.riag.scanpay.config.MongoConfig$StringToZonedDateTime.convert(MongoConfig.java:28)
at org.springframework.core.convert.support.GenericConversionService$ConverterAdapter.convert(GenericConversionService.java:385)
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:40)
... 71 more
看起来,它想将 username
转换为 ZonedDateTime
。问题可能出在我的 MongoConfig 上,其中我有 ZonedDateTime
:
的自定义转换器
@Configuration
public class MongoConfig {
private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;
@Bean
public MongoCustomConversions customConversions(){
List<Converter<?,?>> converters = new ArrayList<>();
converters.add(ZonedDateTimeToStringConverter.INSTANCE);
converters.add(StringToZonedDateTime.INSTANCE);
return new MongoCustomConversions(converters);
}
enum StringToZonedDateTime implements Converter<String, ZonedDateTime> {
INSTANCE;
@Override
public ZonedDateTime convert(String source) {
return ZonedDateTime.parse(source, dateTimeFormatter);
}
}
enum ZonedDateTimeToStringConverter implements Converter<ZonedDateTime, String> {
INSTANCE;
@Override
public String convert(ZonedDateTime source) {
return dateTimeFormatter.format(source);
}
}
}
这些转换器当然不应该用于纯字符串,但它似乎在使用新的 Spring 数据 MongoDB 版本时被触发。谁能指出我的代码遇到的问题,或者最新版本有问题吗?
提前致谢!
Spring Data MongoDB 2.0.7 将 ZonedDateType
视为简单类型。您需要通过添加 @ReadingConverter
/@WritingConverter
.
来将转换器消歧为读写转换器
在您上面的安排中,框架尝试将所有 String
值转换为 ZonedDateTime
。相反,您想在 MongoDB 中将 ZonedDateTime
个对象表示为 String
。因此,将 @WritingConverter
添加到 ZonedDateTimeToStringConverter
并将 @ReadingConverter
添加到另一个可以解决您的问题。
更新到版本 2 后我遇到了同样的问题
我的问题是我们在转换器中使用 DBObject
而不是 org.bson.Document
。例如:
public class MyCustomMappingConverter implements Converter<DBObject, MyClass>
我改成:
解决了
public class MyCustomMappingConverter implements Converter<Document, MyClass>
我今天刚刚升级到 Spring Boot 2.0.2,作为升级的一部分,我还升级到了 Spring-Data-MongoDB 2.0.7.
我有以下实体:
@Document
@Data
public class User {
private String username;
private String password;
private List<String> authorities;
public User(String username, String password, List<String> authorities) {
this.username = username;
this.password = password;
this.authorities = authorities;
}
}
在我的测试中,我使用以下方法插入了一个新用户:
mongoTemplate.save(new User("testuser", "a$OuKj.lXzPxlwgr2Jy28E4ehHuxnVZ7BuL46qX9fd6vAijcDN6UeHe", Collections.singletonList("user")));
这在使用 Spring Boot 2.0.1(分别为 Spring-Data-MongoDB 2.0.6)时完美运行。使用升级后的 Spring-Data-MongoDB 版本,出现以下错误:
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.ZonedDateTime] for value 'testuser'; nested exception is java.time.format.DateTimeParseException: Text 'testuser' could not be parsed at index 0
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:46)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:191)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getPotentiallyConvertedSimpleWrite(MappingMongoConverter.java:849)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeSimpleInternal(MappingMongoConverter.java:829)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeProperties(MappingMongoConverter.java:488)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:462)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:436)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.write(MappingMongoConverter.java:391)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.write(MappingMongoConverter.java:86)
at org.springframework.data.mongodb.core.MongoTemplate.toDocument(MongoTemplate.java:1070)
at org.springframework.data.mongodb.core.MongoTemplate.doSave(MongoTemplate.java:1253)
at org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:1201)
at org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:1185)
....
Caused by: java.time.format.DateTimeParseException: Text 'testuser' could not be parsed at index 0
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
at java.time.ZonedDateTime.parse(ZonedDateTime.java:597)
at at.riag.scanpay.config.MongoConfig$StringToZonedDateTime.convert(MongoConfig.java:34)
at at.riag.scanpay.config.MongoConfig$StringToZonedDateTime.convert(MongoConfig.java:28)
at org.springframework.core.convert.support.GenericConversionService$ConverterAdapter.convert(GenericConversionService.java:385)
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:40)
... 71 more
看起来,它想将 username
转换为 ZonedDateTime
。问题可能出在我的 MongoConfig 上,其中我有 ZonedDateTime
:
@Configuration
public class MongoConfig {
private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;
@Bean
public MongoCustomConversions customConversions(){
List<Converter<?,?>> converters = new ArrayList<>();
converters.add(ZonedDateTimeToStringConverter.INSTANCE);
converters.add(StringToZonedDateTime.INSTANCE);
return new MongoCustomConversions(converters);
}
enum StringToZonedDateTime implements Converter<String, ZonedDateTime> {
INSTANCE;
@Override
public ZonedDateTime convert(String source) {
return ZonedDateTime.parse(source, dateTimeFormatter);
}
}
enum ZonedDateTimeToStringConverter implements Converter<ZonedDateTime, String> {
INSTANCE;
@Override
public String convert(ZonedDateTime source) {
return dateTimeFormatter.format(source);
}
}
}
这些转换器当然不应该用于纯字符串,但它似乎在使用新的 Spring 数据 MongoDB 版本时被触发。谁能指出我的代码遇到的问题,或者最新版本有问题吗?
提前致谢!
Spring Data MongoDB 2.0.7 将 ZonedDateType
视为简单类型。您需要通过添加 @ReadingConverter
/@WritingConverter
.
在您上面的安排中,框架尝试将所有 String
值转换为 ZonedDateTime
。相反,您想在 MongoDB 中将 ZonedDateTime
个对象表示为 String
。因此,将 @WritingConverter
添加到 ZonedDateTimeToStringConverter
并将 @ReadingConverter
添加到另一个可以解决您的问题。
更新到版本 2 后我遇到了同样的问题
我的问题是我们在转换器中使用 DBObject
而不是 org.bson.Document
。例如:
public class MyCustomMappingConverter implements Converter<DBObject, MyClass>
我改成:
解决了public class MyCustomMappingConverter implements Converter<Document, MyClass>