【问题标题】:Spring Mongo Aggregate & LocalDateTime issueSpring Mongo Aggregate & LocalDateTime 问题
【发布时间】:2017-10-18 12:51:04
【问题描述】:

将 Mongo 的聚合与 Java 8 LocalDateTime 条件一起使用时出现以下错误。

引起:org.bson.codecs.configuration.CodecConfigurationException: 找不到类 java.time.LocalDateTime 的编解码器。

下面这段代码

@SpringBootApplication
public class MongojavatimeApplication implements CommandLineRunner {

    @Autowired
    private MongoTemplate template;

    public static void main(String[] args) {
        SpringApplication.run(MongojavatimeApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        Criteria c = Criteria.where("createdDate").gt(LocalDateTime.now().minusDays(30));
        template.aggregate(Aggregation.newAggregation(Aggregation.match(c)), "TestJavaTime", TestJavaTime.class);
    }
}

您会在这里找到很少的测试,LocalDateTime 可以在 Spring 存储库中正常工作,这是使用 MongoTemplate 的 Criteria API 的经典查询,但在创建聚合查询时会引发此错误。 https://github.com/Farael49/spring-mongo-aggregate-localdatetime

我还做了一个小测试,将 LocalDateTime 替换为 java util Date,以表明它没有引发编解码器错误。

有什么我可以做的,还是 Mongo Driver/Spring 问题?

谢谢

【问题讨论】:

    标签: java spring mongodb java-8


    【解决方案1】:

    如果您想直接使用LocalDateTime,您应该提供这样的编解码器:

    public enum LocalDateTimeCodec
            implements Codec<LocalDateTime> {
    
        INSTANCE;
    
        @Override
        public void encode(
                BsonWriter writer,
                LocalDateTime value,
                EncoderContext encoderContext) {
    
            writer.writeDateTime(
                    value.toInstant(ZoneOffset.UTC)
                         .toEpochMilli()
            );
        }
    
        @Override
        public LocalDateTime decode(
                BsonReader reader,
                DecoderContext decoderContext) {
    
            return Instant.ofEpochMilli(reader.readDateTime())
                    .atOffset(ZoneOffset.UTC)
                    .toLocalDateTime();
        }
    
        @Override
        public Class<LocalDateTime> getEncoderClass() {
            return LocalDateTime.class;
        }
    }
    

    你可以这样注册:

    @Bean
    public MongoDbFactory mongoDbFactory() throws Exception {
        CodecRegistry registry = CodecRegistries.fromRegistries(
            CodecRegistries.fromCodecs(LocalDateTimeCodec.INSTANCE),
            MongoClient.getDefaultCodecRegistry()
        );
        MongoClientOptions options = MongoClientOptions
            .builder()
            .codecRegistry(registry)
            .build();
        return new SimpleMongoDbFactory(new MongoClient(host, options), dbName);
    }
    

    其中hostdbName 可能是某些配置类的自动装配字段。

    【讨论】:

      【解决方案2】:

      我认为您的问题是由于 mongodb java 驱动程序不知道如何序列化 LocalDateTime 对象。这里有一个很好的解决这个问题的方法:Cannot serialize LocalDate in Mongodb

      在您的代码中像这样修改它可能会起作用:

      @Override
      public void run(String... args) throws Exception {
          LocalDateTime startDateTime = LocalDateTime.now().minusDays(30);
          Instant startInstant = startDateTime.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
          Criteria c = Criteria.where("createdDate").gt(Date.from(startInstant));
          template.aggregate(Aggregation.newAggregation(Aggregation.match(c)), "TestJavaTime", TestJavaTime.class);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-14
        • 2016-05-11
        • 2021-09-12
        • 1970-01-01
        • 1970-01-01
        • 2019-04-13
        • 2023-01-02
        • 1970-01-01
        相关资源
        最近更新 更多