当前位置: 首页 > 知识库问答 >
问题:

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

戚弘和
2023-03-14

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

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());将字段在DB中保持为日期类型:“someInstant”:ISODate(“2017-07-11T07:26:44.269Z”)

现在,该方法也可以调用为:updateSomeRecordBySomeID(“some-id”,“2017-07-11T07:26:44.269Z”);

在本例中,我得到一个异常:

org.springframework.core.convert.converterNotFoundException:找不到能够从类型[java.lang.String]转换为类型[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”

>

  • 我简化了代码,使其专注于实际问题。实际上,该方法不会接收someinstant字段作为参数。所以写重载方法在这里是不适用的。此外,方法内部任何类型的instanceof检查对于实际场景都不起作用。所以重点在于为什么转换没有发生?

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

  • 共有1个答案

    长孙阳成
    2023-03-14

    您的更新逻辑是以不知道类型的方式编写的:您可以传递任何对象类型(Integer、Long、Boolean、String、Date等),并且它将通过使用新值和新类型重写现有的值/类型而持久化在DB中。注意:像MongoDB这样的面向文档的数据库没有固定的模式,所以存储的数据可以任意改变数据类型。

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

    引入转换器后,读取问题得到了解决,但仅限于stringdate类型。如果您使用一些boolean值更新someinstant属性,那么您将返回到读取对象并将其映射到Java bean的问题。

     类似资料:
    • 我已经按照 Spring.io 指南访问了MongoDB数据,https://spring.io/guides/gs/accessing-mongodb-data-rest/,并且可以将文档保存到mongo中。 当我试图在POJO中添加一个日期字段并将日期设置为< code>new Date()对象时,它只是在保存到mongo时将值保存为null。 我创建了一个非常基本的,它工作正常(传入请求正文

    • 我想使用TypeORM将键值对存储到MongoDB。我的后端API是用NestJs制作的(不确定这是否重要)。键的类型为,值的类型为,因为我想将任何内容存储到此对象。 这是我的TypeForm数据库配置 我的映射实体不会自动生成密钥,因为我想自己设置它 当我想将一个新映射保存到数据库时,我运行这个逻辑(无论在哪里) 我得到这个错误 无法读取未定义的属性属性属性名称 执行数据库实体的功能时。似乎我无

    • 问题内容: 我试图 使用fasterxml jackson在mongo集合中保留具有字段的java对象。问题是objectMapper的默认性质是将Date存储为NumberLong类型。 例如,类型 字段 将如下存储: 我想以mongo Shell中可用的 ISODate 格式存储它。 现在,我知道有一种格式化对象映射器的方法来将Date存储为String dateformat。但是我只在寻找I

    • 我尝试使用spark将一些数据保存到casandra,但当我尝试保存日期时,我得到了 出现以下错误: 我的餐桌课 我的cassandra表: 有人知道怎么解决这个问题吗? 编辑:

    • 从Java驱动程序,我想保存一个文档,看起来像下面的json在MongoDb 我尝试过的选择。 选项1:Map doc=new HashMap(1); 它会产生以下非必需的格式 备选案文2: 其结果是:

    • 问题内容: 我正在使用Jackson 将Java Bean转换为。 但是,它不是保留对象,而是将其转换为。 这是失败的测试用例, 有一个简单的解决方案吗? 问题答案: 默认情况下,Jackson将实例序列化为数字时间戳。您可以将Jackson配置为使用带有 或提供您自己的。 但是,当您进行转换时,中间JSON和目标类型中绝对没有任何内容可向Jackson表示应将其反序列化为对象。如果没有额外的类型