关于mongodb-driver无法解析BigDecimal

2018-12-08  本文已影响0人  soSweety

背景:

springboot项目连接mongoDB数据库,在插入数据到mongDB时报错,异常消息显示没有BigDecimal的Codec。

原因:

跟随异常栈发现MongoDBDriver在转化数据是会从一个Codec注册表中获取相应java类的的Codec,然后重启项目跟随代码发现Codec注册表初始化时并没有添加BigDecimal的Codec,同时也没有BigDecimal的Codec

解决:

首先是实现Codec 创建 BigDecimal 的Codec:

public class MongoBigCodec implements Codec {

@Override

    public BigDecimaldecode(BsonReader bsonReader, DecoderContext decoderContext) {

            return new BigDecimal(bsonReader.readString());

    }

@Override

    public void encode(BsonWriter bsonWriter, BigDecimal bigDecimal, EncoderContext encoderContext) {

         bsonWriter.writeString(bigDecimal.toString());

    }

@Override

    public ClassgetEncoderClass() {  

             return BigDecimal.class;

    }

}

接着在spring初始化时,利用发射将实现的MongoBigCodec添加到Codec注册表:

@Component

public class MongoInitimplements CommandLineRunner {

@Autowired

    private MongoTemplatemongoTemplate;

    @Override

    public void run(String... strings)throws Exception {

Class clazz = (Class) (mongoTemplate.getDb().getMongo()).getClass();

        Field f = clazz.getDeclaredField("DEFAULT_CODEC_REGISTRY");

        f.setAccessible(true);

        CodecRegistry codecRegistry = (CodecRegistry) f.get(mongoTemplate.getDb().getMongo());

        Field cf = codecRegistry.getClass().getDeclaredField("codecProviders");

        cf.setAccessible(true);

        ValueCodecProvider codecProvider = (ValueCodecProvider) ((ArrayList) cf.get(codecRegistry)).get(0);

        Method[] putCs = codecProvider.getClass().getDeclaredMethods();

        Method putC =null;

        for (int i =0; i < putCs.length; i++) {

if (putCs[i].getName().equals("addCodec")) {

putC = putCs[i];

break;

            }

}

putC.setAccessible(true);

        putC.invoke(codecProvider, new MongoBigCodec());

    }

}

再次重启项目,程序能够正常的解析BigDecimal数据类型

上一篇下一篇

猜你喜欢

热点阅读