背景:
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数据类型
网友评论