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

时间:2017-07-11 21:31:49

标签: java spring mongodb mongotemplate jsr310

我有一个具有df$chr1类型成员变量的Java类:

Instant

我使用MongoTemplate更新数据库中的public class SomeRecord { private String someId; private Instant someInstant; // getters and setters } 字段:

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());类型: Date

现在该方法也可以被称为: "someInstant" : ISODate("2017-07-11T07:26:44.269Z")

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

  

org.springframework.core.convert.ConverterNotFoundException:没有   转换器发现能够从类型[java.lang.String]转换为   输入[java.time.Instant]

这完全有道理。 (它会将数据库中的字段更新为updateSomeRecordBySomeId("SOME-ID", "2017-07-11T07:26:44.269Z");String

<小时/> 所以我添加了一个转换器如下:

MongoConfig.java:

"someInstant" : "2017-07-11T07:26:44.269Z"

StringToInstantConverter.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);
    }
}

添加上述转换后,我不再获得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?转换器供应不正确吗?如何为这种情况编写转换器?

注意:

  • 我简化了代码以专注于实际问题。实际上,该方法不会将String字段作为参数接收。因此,编写重载方法不适用于此。此方法中的任何类型someInstant检查都不适用于实际方案。那么关注的重点是转换没有发生的原因?

  • 我们的实际数据存储是DocumentDB,但我们使用DocumentDB with MongoDB API(因为Spring Data不支持DocumentDB)来进行数据库操作。

1 个答案:

答案 0 :(得分:2)

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

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

介绍转换器后,解决了阅读问题,但仅适用于StringDate类型。如果使用某个someInstant值更新boolean属性,您将回到该问题以读取该对象并将其映射到Java bean。