JHipster v5.7.1中QueryDSL操作MongoDB日期字段遇编解码器错误
解决QueryDSL MongoDB查询时的CodecConfigurationException(ZonedDateTime编解码器缺失)
你遇到的问题核心是:虽然实体类已经把日期字段改为Instant,但QueryDSL在处理after/before这类谓词时,仍然在内部使用了ZonedDateTime类型,而你的MongoDB驱动没有配置对应的编解码器,也有可能是之前生成的Q类没有同步更新字段类型。下面是具体的解决步骤:
1. 重新生成QueryDSL的Q类
如果QTurno是在你把字段从ZonedDateTime改成Instant之前生成的,那Q类里的日期字段类型大概率还是ZonedDateTime,这会直接导致查询时类型不匹配。
- 运行Maven命令重新生成Q类:
或者直接调用QueryDSL插件的目标:mvn clean compilemvn querydsl:process - 检查生成的
QTurno类,确认日期字段的类型已经同步为Instant,比如:public final DateTimePath<Instant> fecha = createDateTime("fecha", Instant.class);
2. 配置MongoDB支持Java 8时间类型编解码器
JHipster v5.7.1使用的MongoDB Java驱动版本默认没有内置Java 8时间API(比如Instant、ZonedDateTime)的编解码器,需要手动配置:
方法一:通过Spring的MongoCustomConversions添加转换器
创建一个配置类,注册Instant和ZonedDateTime与MongoDBDate之间的双向转换器:
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.Instant; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Date; import java.util.List; @Configuration public class MongoDbConfiguration { @Bean public MongoCustomConversions mongoCustomConversions() { List<Converter<?, ?>> converters = new ArrayList<>(); // Instant → Date converters.add(new Converter<Instant, Date>() { @Override public Date convert(Instant source) { return Date.from(source); } }); // Date → Instant converters.add(new Converter<Date, Instant>() { @Override public Instant convert(Date source) { return source.toInstant(); } }); // ZonedDateTime → Date(处理QueryDSL内部可能的类型转换) converters.add(new Converter<ZonedDateTime, Date>() { @Override public Date convert(ZonedDateTime source) { return Date.from(source.toInstant()); } }); // Date → ZonedDateTime converters.add(new Converter<Date, ZonedDateTime>() { @Override public ZonedDateTime convert(Date source) { return ZonedDateTime.ofInstant(source.toInstant(), java.time.ZoneId.systemDefault()); } }); return new MongoCustomConversions(converters); } }
方法二:使用MongoDB官方的JSR-310编解码器
如果你的MongoDB驱动版本在3.10及以上,可以直接注册官方提供的编解码器提供者:
import com.mongodb.MongoClientSettings; import org.bson.codecs.configuration.CodecRegistries; import org.bson.codecs.configuration.CodecRegistry; import org.bson.codecs.jsr310.Jsr310CodecProvider; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.MongoClientFactoryBean; @Configuration public class MongoDbConfiguration { @Bean public MongoClientFactoryBean mongoClient() { MongoClientFactoryBean factory = new MongoClientFactoryBean(); // 合并默认编解码器与JSR-310编解码器 CodecRegistry codecRegistry = CodecRegistries.fromRegistries( MongoClientSettings.getDefaultCodecRegistry(), CodecRegistries.fromProviders(new Jsr310CodecProvider()) ); MongoClientSettings settings = MongoClientSettings.builder() .codecRegistry(codecRegistry) .build(); factory.setMongoClientSettings(settings); // 按需配置MongoDB地址(如果JHipster未自动配置) factory.setHost("localhost"); factory.setPort(27017); return factory; } }
3. 规范QueryDSL谓词的使用方式
确保你在构建查询时,传入的参数是Instant类型,避免混用ZonedDateTime:
// 正确示例:用Instant作为查询参数 Predicate predicate = QTurno.turno.fecha.after(Instant.now().minusHours(24)); List<Turno> result = turnoRepository.findAll(predicate);
完成以上步骤后,应该就能解决编解码器缺失的问题,让after/before这类日期谓词正常工作了。
内容的提问来源于stack exchange,提问作者Andrea
相关产品推荐
相关产品推荐

