mongo找不到pojo编解码转换器问题

个人博客

问题描述

异常是在mongo执行存储函数向数据库写入数据的时候发生的,业务伪代码如下:

Document dbObject = new Document();
dbObject.append("$eval", "function(x1,x2,x3){return statisticsFunction(x1, x2, x3);}")
        .append("args", Arrays.asList(arg1, arg2, arg3))
        .append("nolock", true);
Document result = mongoTemplate.executeCommand(dbObject);

在没有升级mongo版本之前,POJO通过继承ReflectionDBObject的方式事项映射转换,版本升级之后即不可使用,出现如下异常:

org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class ...

	at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)
	at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)
	at org.bson.codecs.configuration.ChildCodecRegistry.get(ChildCodecRegistry.java:51)
	at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:184)
	at org.bson.codecs.DocumentCodec.writeIterable(DocumentCodec.java:207)
	at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:180)
	at org.bson.codecs.DocumentCodec.writeIterable(DocumentCodec.java:207)
	at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:180)
	at org.bson.codecs.DocumentCodec.writeMap(DocumentCodec.java:199)
	at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:141)
	at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:45)
问题分析

跟进源码查看异常的抛出点可知,是因为在执行过程中拿不到编解码转换器的原因导致。异常抛出点源码如下:

final class CodecCache {
    private final ConcurrentMap<Class<?>, Optional<? extends Codec<?>>> codecCache =
            new ConcurrentHashMap<Class<?>, Optional<? extends Codec<?>>>();

    public boolean containsKey(final Class<?> clazz) {
        return codecCache.containsKey(clazz);
    }

    public void put(final Class<?> clazz, final Codec<?> codec){
        codecCache.put(clazz, Optional.of(codec));
    }

    @SuppressWarnings("unchecked")
    public <T> Codec<T> getOrThrow(final Class<T> clazz) {
        if (codecCache.containsKey(clazz)) {
            Optional<? extends Codec<?>> optionalCodec = codecCache.get(clazz);
            if (!optionalCodec.isEmpty()) {
                return (Codec<T>) optionalCodec.get();
            }
        }
        throw new CodecConfigurationException(format("Can't find a codec for %s.", clazz));
    }
}

ReflectionDBObject 是mongo一种老的POJO映射方式,所使用的POJO需要继承它,在新版本已不适用,目前bson提供了POJO的映射支持。

解决方案

参考mongo官方文档

首先需要注册bson的POJO编解码器;

CodecRegistry pojoCodecRegistry = fromRegistries(MongoClient.getDefaultCodecRegistry(),
                fromProviders(PojoCodecProvider.builder().automatic(true).build()))

在使用的时候可以选择如下任意一种方式:

  • 在创建MongoClient实例的时候设置pojoCodecRegistry
MongoClientSettings settings = MongoClientSettings.builder()
        .codecRegistry(pojoCodecRegistry)
        .build();
MongoClient mongoClient = MongoClients.create(settings);
  • 在使用MongoDatabase实例的时候设置pojoCodecRegistry
database = database.withCodecRegistry(pojoCodecRegistry);
  • 在使用MongoCollection实例的时候设置pojoCodecRegistry
collection = collection.withCodecRegistry(pojoCodecRegistry);

这里选择是使用通过在使用MongoDatabase实例的时候设置pojoCodecRegistry的方式,业务伪代码改变如下:

Document dbObject = new Document();
dbObject.append("$eval", "function(x1,x2,x3){return statisticsFunction(x1, x2, x3);}")
        .append("args", Arrays.asList(arg1, arg2, arg3))
        .append("nolock", true);
Document result = mongoTemplate.getDb().withCodecRegistry(pojoCodecRegistry).runCommand(dbObject);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值