gpt4 book ai didi

java - Spring Mongodb - 无法为 java.time.Period 编写自定义转换器

转载 作者:行者123 更新时间:2023-12-01 09:35:09 25 4
gpt4 key购买 nike

我将 Spring Cloud Brixton.SR4 与 Spring Data MongoDB 结合使用。

我有一个非常简单的实体:

@Document
public class Foo{
private Period period;

//getter & setter
}

因为 java.time.Period 不受 jsr310 支持,我正在创建自定义转换器:

class Converters {
@Component
@WritingConverter
static class PeriodToStringConverter implements Converter<Period, String> {
@Override
public String convert(Period period) {
return period.toString();
}
}

@ReadingConverter
@Component
static class StringToPeriodConverter implements Converter<String, Period> {

@Override
public Period convert(String s) {
return Period.parse(s);
}
}

现在我将它们注册到扩展 AbstractMongoConfiguration 的配置类中:

    @Bean
@Override
public MappingMongoConverter mappingMongoConverter() throws Exception {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext());
final CustomConversions conversions = customConversions();
log.info("hasCustomWriteTarget(Period.class): " + conversions.hasCustomWriteTarget(Period.class));
log.info("hasCustomWriteTarget(Period.class, String.class): " + conversions.hasCustomWriteTarget(Period.class, String.class));
log.info("hasCustomReadTarget(String.class, Period.class): " + conversions.hasCustomReadTarget(String.class, Period.class));
converter.setCustomConversions(conversions);
converter.afterPropertiesSet(); //probably not needed, trying out of despair
return converter;
}

@Bean
@Override
public CustomConversions customConversions() {
List<Converter> converters = new ArrayList<>();
converters.add(new Converters.PeriodToStringConverter());
converters.add(new Converters.StringToPeriodConverter());
return new CustomConversions(converters);
}

当我启动应用程序时,我在日志中看到:

hasCustomWriteTarget(Period.class): true
hasCustomWriteTarget(Period.class, String.class): true
hasCustomReadTarget(String.class, Period.class): true

现在我创建一个新的 Foo 并将其保存到我的存储库中:

Foo foo = new Foo();
foo.setPeriod(Period.of(2, 0, 1));
fooRepository.save(foo);

现在奇怪的事情发生了:

在 Mongodb 中我看到:

{
"_id": ObjectId("xxxx"),
"period": {
"years" : 0,
"months" : 2,
"days" : 1
}
}

所以这已经是错误的了。它应该保存为 String

当我尝试读取 Java 中的对象时,我得到:

org.springframework.data.mapping.model.MappingException: No property null found on entity class java.time.Period to bind constructor parameter to!

我调试了MappingMongoConverter中的代码:

    if (conversions.hasCustomReadTarget(dbo.getClass(), rawType)) {
return conversionService.convert(dbo, rawType);
}

因为我的对象没有存储为字符串,所以 dbo 变量实际上是一个 BasicDbObject,因此我没有用于此的转换器。

知道为什么我的写入转换器没有被用来持久化Period吗?

我的类路径上有 jackson-datatype-jdk8,这可能是问题所在吗? Jackson 会因为坚持使用 Mongodb 而参与其中吗?

编辑

这似乎是一个注册问题。当我调试代码时,MappingMongoConverter 中使用的 CustomConversion 对象与我创建的对象不同。而且它没有我创建的自定义转换器

最佳答案

好吧,这非常愚蠢......

我还创建了自己的 MongoTemplate:

@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory());
}

这基本上忽略了我的自定义转换器。修复它:

@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
}

关于java - Spring Mongodb - 无法为 java.time.Period 编写自定义转换器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39042344/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com