如何使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
相关产品推荐
相关产品推荐

