You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使ReactiveMongoRepository插入后直接返回转换后的Instant值?

解决方案

要让ReactiveMongoRepository插入后返回与Mongo存储一致的毫秒精度Instant值,有以下几种可行方案:

方案一:插入后立即查询实体

利用反应式流的flatMap操作,在插入完成后直接执行查询,获取Mongo中实际存储的实体。这样返回的结果自然是经过毫秒截断的:

// 反应式写法(非阻塞)
myReactiveMongoRepository.insert(entity)
    .flatMap(saved -> myReactiveMongoRepository.findById(saved.getId()))
    .subscribe(loaded -> {
        System.out.println("loaded.getSent() = " + loaded.getSent());
        // 输出为2022-09-17T00:20:58.399Z
    });

// 阻塞式写法(和你原代码风格一致)
MyEntity inserted = myReactiveMongoRepository.insert(entity)
    .flatMap(saved -> myReactiveMongoRepository.findById(saved.getId()))
    .block();
System.out.println("inserted.getSent() = " + inserted.getSent());

方案二:主动截断Instant到毫秒精度

在插入前就把Instant值截断到毫秒,这样插入返回的实体和Mongo存储的值一致。可以通过两种方式实现:

方式1:在实体的setter方法中处理

修改实体类的setSent方法,主动截断精度:

public class MyEntity {
    private Instant sent;

    public void setSent(Instant sent) {
        // 截断到毫秒精度
        this.sent = sent.truncatedTo(ChronoUnit.MILLIS);
    }

    // 其他getter、setter和字段
}

方式2:自定义Mongo类型转换器

实现Mongo的Converter,将Instant转换为Date时自动截断到毫秒:

import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import java.time.Instant;
import java.util.Date;

@WritingConverter
public class InstantToDateConverter implements Converter<Instant, Date> {
    @Override
    public Date convert(Instant source) {
        // 截断到毫秒后转Date
        return Date.from(source.truncatedTo(ChronoUnit.MILLIS));
    }
}

@ReadingConverter
public class DateToInstantConverter implements Converter<Date, Instant> {
    @Override
    public Instant convert(Date source) {
        return source.toInstant();
    }
}

然后将这些转换器注册到Mongo配置中:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import java.util.List;

@Configuration
public class MongoConfig {
    @Bean
    public MongoCustomConversions mongoCustomConversions() {
        return new MongoCustomConversions(List.of(
            new InstantToDateConverter(),
            new DateToInstantConverter()
        ));
    }
}

方案三:重写Repository的insert方法

自定义Repository接口和实现类,重写insert逻辑,插入后直接查询返回:

1. 自定义Repository接口

import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import reactor.core.publisher.Mono;

public interface CustomMyEntityRepository {
    Mono<MyEntity> insertAndReturnStored(MyEntity entity);
}

public interface MyReactiveMongoRepository extends ReactiveMongoRepository<MyEntity, String>, CustomMyEntityRepository {
}

2. 实现自定义方法

import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import reactor.core.publisher.Mono;

public class CustomMyEntityRepositoryImpl implements CustomMyEntityRepository {
    private final ReactiveMongoTemplate mongoTemplate;
    private final MyReactiveMongoRepository repository;

    public CustomMyEntityRepositoryImpl(ReactiveMongoTemplate mongoTemplate, MyReactiveMongoRepository repository) {
        this.mongoTemplate = mongoTemplate;
        this.repository = repository;
    }

    @Override
    public Mono<MyEntity> insertAndReturnStored(MyEntity entity) {
        return repository.insert(entity)
            .flatMap(saved -> mongoTemplate.findById(saved.getId(), MyEntity.class));
    }
}

之后直接调用insertAndReturnStored方法,就能拿到截断后的实体。


内容的提问来源于stack exchange,提问作者István Békési

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 13:40:54