如何使用Spring MongoTemplate将Java 8 Instant作为日期类型保存到MongoDB?

我有一个具有Instant类型成员变量的Java类:public class SomeRecord {private String someId;private Instant someInstant;// getters and setters}我使用MongoTemplate更新数据库中的someInstant字段:public Som...

我有一个具有Instant类型成员变量的Java类:

public class SomeRecord {
    private String someId;

    private Instant someInstant;

    // getters and setters
}

我使用MongoTemplate更新数据库中的someInstant字段:

public SomeRecord updateSomeRecordBySomeId(final String someId, Object someInstant) {
        Query query = new Query();
        query.addCriteria(Criteria.where("someId").is(someId));

        Update update = new Update();
        update.set("someInstant", someInstant);

        return operations.findAndModify(query, update, new FindAndModifyOptions().returnNew(true), SomeRecord.class);
}

如果我将方法调用为:

updateSomeRecordBySomeId(“SOME-ID”,Instant.now());
将数据库中的字段作为日期类型保留:
“someInstant”:ISODate(“2017-07-11T07:26:44.269Z”)

现在该方法也可以称为:
updateSomeRecordBySomeId(“SOME-ID”,“2017-07-11T07:26:44.269Z”);

在这种情况下,我得到一个例外:

org.springframework.core.convert.ConverterNotFoundException: No
converter found capable of converting from type [java.lang.String] to
type [java.time.Instant]

这完全有道理. (它将DB中的字段更新为字符串.“someInstant”:“2017-07-11T07:26:44.269Z”)

所以我添加了一个转换器如下:

MongoConfig.java:

@Configuration
@ComponentScan(basePackages = {"dao package path here"})
public class MongoConfig {
    @Autowired
    private MongoDbFactory mongoDbFactory;

    @Bean
    public MongoTemplate mongoTemplate() {
        MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory),
                new MongoMappingContext());

        converter.setCustomConversions(new CustomConversions(Collections.singletonList(new StringToInstantConverter())));

        return new MongoTemplate(mongoDbFactory, converter);
    }
}

StringToInstantConverter.java:

public class StringToInstantConverter implements Converter<String, Instant> {
    @Override
    public Instant convert(String utcString) {
        // TODO: Make it generic for any time-zone
        return Instant.parse(utcString);
    }
}

将上述转换后,我没有得到任何ConverterNotFoundException长,但场someInstant正在持续为纯字符串:“someInstant”:“2017-07-11T07:26:44.269Z”

这就是我的问题所在.我知道正在识别转换器,这就是我不再获得异常的原因.但是为什么转换器没有将String转换为Instant?为什么字段被保持为普通字符串?转换器供应不正确吗?如何为这种情况编写转换器?

注意:

>我简化了代码以专注于实际问题.实际上,该方法不接收someInstant字段作为参数.因此,编写重载方法不适用于此.此外,方法内的任何类型的instanceOf检查都不适用于实际场景.所以关注的重点是为什么转换没有发生?
>我们的实际数据存储是DocumentDB,但我们使用DocumentDB with MongoDB API(因为Spring Data不支持DocumentDB)来进行数据库操作.

解决方法:

您的更新逻辑以类型不可知的方式编写:您可以传递任何对象类型(整数,长整数,布尔值,字符串,日期等),并通过使用新值和新类型覆盖现有值/类型将其保留在DB中.注意:面向文档的数据库像MongoDB一样没有固定的模式,因此存储的数据可以随意更改数据类型.

在使用ConverterNotFoundException引入转换器之前的问题不是在更新操作期间,而是在检索更新的对象并将其设置为Java bean模型期间:Java类将someInstant属性定义为Instant / Date类型,但数据库提供了String值.

介绍转换器后,解决了读取问题,但仅限于String和Date类型.如果使用某个布尔值更新someInstant属性,则会回到该问题以读取对象并将其映射到Java bean.

本文标题为:如何使用Spring MongoTemplate将Java 8 Instant作为日期类型保存到MongoDB?

基础教程推荐