简体   繁体   English

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

[英]How to save Java 8 Instant to MongoDB as Date type using Spring MongoTemplate?

I have a Java class having an Instant type of member variable: 我有一个具有Instant类型成员变量的Java类:

public class SomeRecord {
    private String someId;

    private Instant someInstant;

    // getters and setters
}

I am using MongoTemplate to update the someInstant field in database: 我使用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);
}

This works great if I am calling the method as: 如果我将方法调用为:

updateSomeRecordBySomeId("SOME-ID", Instant.now()); persisting the field in DB as a Date type: "someInstant" : ISODate("2017-07-11T07:26:44.269Z") 将数据库中的字段保存为Date类型: "someInstant" : ISODate("2017-07-11T07:26:44.269Z")


Now the method may also be called as: updateSomeRecordBySomeId("SOME-ID", "2017-07-11T07:26:44.269Z"); 现在该方法也可以被称为: updateSomeRecordBySomeId("SOME-ID", "2017-07-11T07:26:44.269Z");

In this case I get an exception as: 在这种情况下,我得到一个例外:

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.time.Instant] org.springframework.core.convert.ConverterNotFoundException:找不到能够从类型[java.lang.String]转换为类型[java.time.Instant]的转换器

which makes complete sense. 这完全有道理。 (It updates the field in the DB as String though. "someInstant" : "2017-07-11T07:26:44.269Z" ) (它将DB中的字段更新为String"someInstant" : "2017-07-11T07:26:44.269Z"


So I added a converter as follows: 所以我添加了一个转换器如下:

MongoConfig.java: MongoConfig.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);
    }
}

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

After adding the above converter I am not getting ConverterNotFoundException any longer, but the field someInstant is being persisted as plain string: "someInstant" : "2017-07-11T07:26:44.269Z" 添加上面的转换器后,我不再获得ConverterNotFoundException ,但字段someInstant被保存为普通字符串: "someInstant" : "2017-07-11T07:26:44.269Z"

And that's what my question is. 这就是我的问题所在。 I know that the converter is being identified that is the reason I am not getting the exception anymore. 我知道正在识别转换器,这就是我不再获得异常的原因。 But why the converter is not converting the String to Instant ? 但是为什么转换器没有将String转换为Instant Why the field is being persisted as plain String ? 为什么字段被保持为普通String Is the converter supplied incorrect? 转换器供应不正确吗? How to write converter for this case? 如何为这种情况编写转换器?

Note: 注意:

  • I have simplified the code to focus on the actual problem. 我简化了代码以专注于实际问题。 In actual the method does not receive the someInstant field as parameter. 实际上,该方法不接收someInstant字段作为参数。 So writing overloaded method is not going to be applicable here. 因此,编写重载方法不适用于此。 Also any kind of instanceOf check inside the method won't work for the actual scenario. 此外,方法内的任何类型的instanceOf检查都不适用于实际场景。 So the focus is on the question why the conversion not happening? 所以关注的重点是为什么转换没有发生?

  • The actual data-store for us is DocumentDB, but we use DocumentDB with MongoDB API (as Spring Data does not support DocumentDB) for our database operations. 我们的实际数据存储是DocumentDB,但我们使用DocumentDB和MongoDB API (因为Spring Data不支持DocumentDB)来进行数据库操作。

Your update logic is written in type agnostic way: you can pass any object type (Integer, Long, Boolean, String, Date, etc.) and it will be persisted in DB by overriding the existing value/type with new value and new type . 您的更新逻辑以类型不可知的方式编写:您可以传递任何对象类型(整数,长整数,布尔值,字符串,日期等),并通过使用新值新类型覆盖现有值/类型将其保留在DB中。 Note: document oriented databased like MongoDB have no fixed schema, so stored data can arbitrary change data types. 注意:面向文档的数据库像MongoDB一样没有固定的模式,因此存储的数据可以随意更改数据类型。

The issue you had before you introduced converter with ConverterNotFoundException was not during update action, but during retrieval of updated object and setting it into your Java bean model: Java class defined someInstant property to be of an Instant / Date type, but database supplied a String value. 您在使用ConverterNotFoundException引入转换ConverterNotFoundException之前遇到的问题不是在更新操作期间,而是在检索更新的对象并将其设置为Java bean模型期间:Java类将someInstant属性定义为Instant / Date类型,但数据库提供了String值。

After you introduced a converter the issue of reading was solved, but only for String and Date types. 介绍转换器后,解决了读取问题,但仅限于StringDate类型。 If you update the someInstant property with some boolean value, you'll get back to the issue to read the object and map it to you Java bean. 如果使用某个boolean值更新someInstant属性,则会回到该问题以读取对象并将其映射到Java bean。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Java将MongoDB对象ID转换为Java日期或Instant - How to convert the MongoDB object id to a Java Date or Instant using Java 如何使用spring mongoTemplate使用DbRef升级MongoDB文档 - How to upsert MongoDB Document with DbRef using spring mongoTemplate 在Spring Boot中使用MongoTemplate检查MongoDB连接 - Check MongoDB connection using MongoTemplate in Spring Boot Java Spring,使用MongoTemplate和通用类型查找 - Java Spring, find with MongoTemplate and generic type 使用 SpringData-MongoDB 将 Java 8 Instant 存储为 BSON 日期 - Store Java 8 Instant as BSON date using SpringData-MongoDB 如何使用 redis 序列化 Java Instant 类型 - How to serialize Java Instant type using redis 如何在Java Spring的mongoTemplate聚合中实现$ SetIsSubset? - How to implement $SetIsSubset in mongoTemplate aggregation of Java Spring? 如何在不使用 mongoTemplate.executeCommand(..) 的情况下使用 spring-data-mongodb 创建视图? - How do I create a view using spring-data-mongodb without resorting to mongoTemplate.executeCommand(..)? 如何使用 JsonFormat 注释或任何其他弹簧日期注释验证 Instant 类型字段的 ISO 标准格式的日期值? - How to validate Date value in ISO Standard format for Instant type field using JsonFormat annotations or any other spring date annotations? 如何将日期从 shell 脚本传递到 java 即时数据类型 - How to pass date from shell script to java Instant data type
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM