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

Spring Data MongoDB中LocalDateTime闭区间日期查询报错问题

解决Spring Data MongoDB中LocalDateTime闭区间查询的序列化问题

我之前在项目里也碰到过一模一样的问题!用Between方法查出来的结果是开区间,换成GreaterThanEqual+LessThanEqual组合又报序列化错误,核心原因就是Spring Data MongoDB默认没做好Java 8新日期类型(java.time.LocalDateTime)和MongoDB原生DateTime类型的转换适配。

问题根源

MongoDB的Java驱动默认只支持序列化java.util.Date这类旧日期类型,而LocalDateTime是Java 8引入的无时区日期类型,直接传入会导致序列化失败,这就是你看到json can't serialize type : class java.time.LocalDateTime错误的原因。

解决方案:自定义Mongo类型转换器

我们需要给Spring Data MongoDB注册自定义的转换器,让它能正确处理LocalDateTime和MongoDBorg.bson.types.DateTime之间的互转,同时建议统一用UTC时区避免时区差异带来的查询误差。

1. 创建Mongo配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class MongoDateTimeConfig {

    @Bean
    public MongoCustomConversions mongoCustomConversions() {
        List<Converter<?, ?>> converters = new ArrayList<>();
        converters.add(new LocalDateTimeToMongoDateTimeConverter());
        converters.add(new MongoDateTimeToLocalDateTimeConverter());
        return new MongoCustomConversions(converters);
    }

    // LocalDateTime转MongoDB DateTime
    static class LocalDateTimeToMongoDateTimeConverter implements Converter<LocalDateTime, org.bson.types.DateTime> {
        @Override
        public org.bson.types.DateTime convert(LocalDateTime source) {
            if (source == null) {
                return null;
            }
            // 统一转成UTC时区存储
            return new org.bson.types.DateTime(
                java.util.Date.from(source.atZone(ZoneOffset.UTC).toInstant())
            );
        }
    }

    // MongoDB DateTime转LocalDateTime
    static class MongoDateTimeToLocalDateTimeConverter implements Converter<org.bson.types.DateTime, LocalDateTime> {
        @Override
        public LocalDateTime convert(org.bson.types.DateTime source) {
            if (source == null) {
                return null;
            }
            // 从UTC时区转回LocalDateTime
            return source.toInstant().atZone(ZoneOffset.UTC).toLocalDateTime();
        }
    }
}

2. 重新使用你的查询方法

配置完转换器后,之前报错的方法就能正常工作了:

List<YourEntity> findAllByMetadataStartTimeGreaterThanEqualAndMetadataStartTimeLessThanEqual(LocalDateTime start, LocalDateTime end);

备选方案:自定义@Query查询

如果你不想用方法名解析,也可以直接写MongoDB查询语句,效果是一样的:

@Query("{'metadata.startTime': {$gte: ?0, $lte: ?1}}")
List<YourEntity> findByMetadataTimeRange(LocalDateTime start, LocalDateTime end);

关于Between方法的小补充

你提到findAllByMetadataStartTimeBetween(start, end)是开区间,大概率是时区差异导致的!因为LocalDateTime不带时区,存储到MongoDB时会转成UTC,而你查询用的是本地时区的时间,导致边界值被过滤掉。用上面的UTC统一配置后,Between方法其实应该是闭区间查询,你可以再测试验证一下。

内容的提问来源于stack exchange,提问作者pennstatephil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:18:50