Java MongoDB驱动POJO编解码报错:找不到'Optional'公共构造函数
异常原因
你遇到的报错不是你的实体类CollectionOrProduct的构造函数有问题,本质是MongoDB默认的POJO编解码器不支持java.util.Optional类型的反序列化:
Optional是JDK提供的不可变容器类,没有公共无参构造函数,默认的PojoCodecProvider自动扫描模式下无法实例化该类型对象,因此抛出找不到公共构造函数的异常。
解决方法
有三种常用的解决方案,可按需选择:
方案1:替换属性类型(最简单通用)
直接把实体类的属性类型从Optional<List<SelectOptionModel>>改为List<SelectOptionModel>,业务侧需要使用Optional时,在getter方法里自行封装即可:
@Introspected public class CollectionOrProduct { private List<SelectOptionModel> product; private List<SelectOptionModel> collection; public CollectionOrProduct() { } public CollectionOrProduct(List<SelectOptionModel> product, List<SelectOptionModel> collection) { this.product = product; this.collection = collection; } public Optional<List<SelectOptionModel>> getProduct() { return Optional.ofNullable(product); } public Optional<List<SelectOptionModel>> getCollection() { return Optional.ofNullable(collection); } public void setProduct(List<SelectOptionModel> product) { this.product = product; } public void setCollection(List<SelectOptionModel> collection) { this.collection = collection; } }
不需要修改其他业务逻辑,也不需要调整编解码器配置。
方案2:注册Optional专用编解码器
如果必须保留属性为Optional类型,可以自定义Optional编解码器或者引入官方扩展的OptionalCodec,将其添加到你的编解码器注册表中:
// 先定义OptionalCodecProvider,或者直接引入第三方已经实现好的实现 public class OptionalCodecProvider implements CodecProvider { @Override public <T> Codec<T> get(Class<T> clazz, CodecRegistry registry) { if (clazz == Optional.class) { return (Codec<T>) new OptionalCodec(registry); } return null; } } // 修改你Repository中的CodecRegistry构造逻辑,提前注册Optional的编解码器 CodecRegistry pojoCodecRegistry = fromRegistries( MongoClientSettings.getDefaultCodecRegistry(), fromProviders(new OptionalCodecProvider()), fromProviders(PojoCodecProvider.builder().automatic(true).build()) );
如果你使用的是Spring Data MongoDB、Micronaut Data MongoDB等框架,高版本已经内置了Optional类型的编解码器支持,升级到对应版本后不需要自行实现。
方案3:标记字段忽略序列化
如果该字段不需要持久化到MongoDB,可以直接加@BsonIgnore注解忽略该字段的编解码处理,即可避开报错。
内容的提问来源于stack exchange,提问作者San Jaisy
相关产品推荐
相关产品推荐

