转自:https://blog.csdn.net/weixin_41792559/article/details/79575524

1.Decimal128的了解
由于mongodb4.3以上新加了Decimal128类型。Decimal128类型对小数给了最好的支持,而double类型对小数存在精度的问题。个人觉得Decimal128还是不错的。但是我测试发现spring-data-mongodb 1.*和现在的spring-data-mongodb2.0.5目前不支持Decimal128自动转换为java的BigDecimal类型。
异常: No converter found capable of converting from type [org.bson.types.Decimal128] to type [java.math.BigDecimal]
大概就是描述:没有Decimal128转换成BigDecimal的转换器。

2.访问mongodb方式:spring-data-mongodb的MongoTemplate。
目前先以spring-data-mongodb的MongoTemplate方式为案例。之后我会增加mongodb原始的dom处理方式,以及spring-boot-starter-data-mongodb下开启了对Repository的支持方式进行测试一下。(进行了测试)
代码:https://github.com/topsnowwolf/mongodbit

3.如何解决Decimal128,BigDecimal的类型转换问题呢?
思路:没有转换器我们新加一个转换。如何新加呢?增加之后如何配置呢?这就是重点了。
首先spring增加类型转换器有 三种方式。

1.实现GenericConverter接口

2.实现ConverterFactory接口

3.实现Converter接口

这三种方式分别如何实现类型转换器,我就不多说了。网上很多例子。

下面我就以实现Converter接口方式的来实现。

自定义类型转换器:

package com.wolf.mongodbit.converter;

import org.bson.types.Decimal128;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter; import java.math.BigDecimal; @ReadingConverter
@WritingConverter
public class BigDecimalToDecimal128Converter implements Converter<BigDecimal, Decimal128> { public Decimal128 convert(BigDecimal bigDecimal) {
return new Decimal128(bigDecimal);
} }
package com.wolf.mongodbit.converter;

import org.bson.types.Decimal128;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter; import java.math.BigDecimal; @ReadingConverter
@WritingConverter
public class Decimal128ToBigDecimalConverter implements Converter<Decimal128, BigDecimal> { public BigDecimal convert(Decimal128 decimal128) {
return decimal128.bigDecimalValue();
} }

下面我就分析一下MongoTemplate的源码。

我们先带着问题去看。我们增加了转换器,这个转换器是给访问mongodb用的,那肯定是给MongoTemplate设置新的转换器了。

打开MongoTemplate这个类,果然如此。MongoTemplate的构造方法中就有一个参数是设置类型转换器的。看到希望了。哈哈!

    public MongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter mongoConverter) {
this.writeConcernResolver = DefaultWriteConcernResolver.INSTANCE;
this.writeResultChecking = WriteResultChecking.NONE;
Assert.notNull(mongoDbFactory, "MongoDbFactory must not be null!");
this.mongoDbFactory = mongoDbFactory;
this.exceptionTranslator = mongoDbFactory.getExceptionTranslator();
this.mongoConverter = mongoConverter == null ? getDefaultMongoConverter(mongoDbFactory) : mongoConverter;
this.queryMapper = new QueryMapper(this.mongoConverter);
this.updateMapper = new UpdateMapper(this.mongoConverter);
this.mappingContext = this.mongoConverter.getMappingContext();
if (null != this.mappingContext && this.mappingContext instanceof MongoMappingContext) {
this.indexCreator = new MongoPersistentEntityIndexCreator((MongoMappingContext)this.mappingContext, mongoDbFactory);
this.eventPublisher = new MongoMappingEventPublisher(this.indexCreator);
if (this.mappingContext instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware)this.mappingContext).setApplicationEventPublisher(this.eventPublisher);
}
} }

最终发现MongoConverter是一个接口。那一定有实现它的类。查一下api发现,抽象的类AbstractMongoConverter,最后是MappingMongoConverter类。此时就会发现AbstractMongoConverter类中有setCustomConversions设置自定义类型转换器的set方法。现在兴奋了吧!!!

现在大概的思路就是通过创建一个MappingMongoConverter对象,将定义的类型转换器调用setCustomConversions方法进行注册。最后调用MongoTemplate的构造方法得到MongoTemplate对象。

废话不多说上代码:

自定义一个配置类:

package com.wolf.mongodbit.config;

import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.wolf.mongodbit.converter.BigDecimalToDecimal128Converter;
import com.wolf.mongodbit.converter.Decimal128ToBigDecimalConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import java.util.ArrayList;
import java.util.List;
@Configuration
public class MongodbConfig extends AbstractMongoConfiguration{
private String dbName = "wolf";
@Override
public MongoClient mongoClient() {
MongoClient mongoClient = new MongoClient();
return mongoClient;
} @Override
protected String getDatabaseName() {
return dbName;
}
@Bean
public MappingMongoConverter mappingMongoConverter() throws Exception {
DefaultDbRefResolver dbRefResolver = new DefaultDbRefResolver(this.dbFactory());
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, this.mongoMappingContext());
List<Object> list = new ArrayList<>();
list.add(new BigDecimalToDecimal128Converter());//自定义的类型转换器
list.add(new Decimal128ToBigDecimalConverter());//自定义的类型转换器
converter.setCustomConversions(new MongoCustomConversions(list));
return converter;
}
@Bean
public MongoDbFactory dbFactory() throws Exception {
return new SimpleMongoDbFactory(new MongoClientURI("mongodb://localhost:27017/wolf"));
}
@Bean
public MongoMappingContext mongoMappingContext() {
MongoMappingContext mappingContext = new MongoMappingContext();
return mappingContext;
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(this.dbFactory(), this.mappingMongoConverter());
}
}

实体类:

package com.wolf.mongodbit.entity.mongodb;

import lombok.Data;

@Data
public class Address {
private String aCode;
private String add;
}
package com.wolf.mongodbit.entity.mongodb;

import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.mapping.Document; import java.util.Date; @Document(collection="blacklist")
@Data
public class Blacklist {
private ObjectId objectId;
private String username;
private String userid;
private String blacktype;
private String status;
private Date update;
private Date indate;
private Address address;
private Comments comments;
}
package com.wolf.mongodbit.entity.mongodb;

import lombok.Data;

import java.math.BigDecimal;
@Data
public class Comments {
private String cause;
private String desc;
private BigDecimal money;
}

测试的controller:

package com.wolf.mongodbit.controller;

import com.wolf.mongodbit.entity.mongodb.Blacklist;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import java.util.List; import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query; @RestController
@RequestMapping("/mongodb")
public class BlackListController {
private final static Logger logger = LoggerFactory.getLogger(BlackListController.class);
@Autowired
private MongoTemplate mongoTemplate;
@PostMapping("/check")
private Blacklist checkBlack(Blacklist blackList){
List<Blacklist> list = mongoTemplate.find(query(where("userid").is(blackList.getUserid())), Blacklist.class);
logger.info("springboot+mongodb:size={}",list.size());
if(list.size()>0)
return list.get(0);
return null;
}
}

pom配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.wolf</groupId>
<artifactId>mongodbit</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>mongodbit</name>
<description>Demo project for Spring Boot</description> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <!--lombok自动生成实体类get/set方法 start-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--lombok自动生成实体类get/set方法 end--> <!--mongodb引入 start -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
</dependency>
<!--
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
-->
<!--mongodb引入 end -->
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

yml配置文件:

#访问项目的url前缀
server:
servlet:
context-path: /mongodb

mongodb的测试数据:

var blacklist1 = {
"username" : "snowwolf",
"userid" : "2018001014344",
"address" : {
"aCode" : "0020",
"add" : "广州"
},
"certificate":{
"certificateid":"20018554111134",
"certificatetype":"01",
"desc":"学生证"
},
"blacktype" : "01",
"comments":{
"cause":"01",
"desc":"逾期欠费",
"money":NumberDecimal("18889.09")
},
"status":"01",
"update" : ISODate("2017-12-06T04:26:18.354Z"),
"indate" : ISODate("2017-12-06T04:26:18.354Z") };
var blacklist2 = {
"username" : "lison",
"userid" : "2018001014345",
"address" : {
"aCode" : "0075",
"add" : "深圳"
},
"certificate":{
"certificateid":"20018554111134",
"certificatetype":"02",
"desc":"护照"
},
"blacktype" : "01",
"comments":{
"cause":"02",
"desc":"恶意欠费",
"money":NumberDecimal("188890.00")
},
"status":"01",
"update" : ISODate("2016-01-06T04:26:18.354Z"),
"indate" : ISODate("2015-12-06T04:26:18.354Z") };
var blacklist3 = {
"username":"tom",
"userid":"2018001014346",
"address":{
"aCode" : "0020",
"add" : "广州"
},
"certificate":{
"certificateid":"20018554111136",
"certificatetype":"01",
"desc":"学生证"
},
"blacktype":"01",
"comments":{
"cause":"03",
"desc":"公安机关确定的涉嫌短信欺诈、诈骗等犯罪行为的用户"
},
"status":"01",
"update":ISODate("2017-12-06T04:26:18.354Z"),
"indate":ISODate("2017-12-06T04:26:18.354Z") }; db.blacklist.insert(blacklist1);
db.blacklist.insert(blacklist2);
db.blacklist.insert(blacklist3);

在postman中测试:

结果完美!

时间有限,有些地方可能不是很完美!不足之处请大牛指出,谢谢!

有需要代码的我之后将会发布到git上!

https://github.com/topsnowwolf/mongodbit

springboot整合mongodb问题1-Decimal128和BigDecimal的转换之mongodb转换器使用(转)的更多相关文章

  1. SpringBoot整合mybatis——配置mybatis驼峰命名规则自动转换

    一.简述 mybatis驼峰式命名规则自动转换: 使用前提:数据库表设计按照规范“字段名中各单词使用下划线"_"划分”: 使用好处:省去mapper.xml文件中繁琐编写表字段列表 ...

  2. 四、SpringBoot整合mybatis——配置mybatis驼峰命名规则自动转换

    简述: mybatis驼峰式命名规则自动转换: 使用前提:数据库表设计按照规范“字段名中各单词使用下划线"_"划分”:使用好处:省去mapper.xml文件中繁琐编写表字段列表与表 ...

  3. java操作mongodb & springboot整合mongodb

    简单的研究原生API操作MongoDB以及封装的工具类操作,最后也会研究整合spring之后作为dao层的完整的操作. 1.原生的API操作 pom.xml <!-- https://mvnre ...

  4. SpringBoot整合mongoDB

    MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的. 这一片文章介绍一个springboot整合mongodb,如果你了解整合mysql之类的 ...

  5. SpringBoot 整合mongoDB并自定义连接池

    SpringBoot 整合mongoDB并自定义连接池 得力于SpringBoot的特性,整合mongoDB是很容易的,我们整合mongoDB的目的就是想用它给我们提供的mongoTemplate,它 ...

  6. springboot整合mybatis,mongodb,redis

    springboot整合常用的第三方框架,mybatis,mongodb,redis mybatis,采用xml编写sql语句 mongodb,对MongoTemplate进行了封装 redis,对r ...

  7. 实例讲解Springboot整合MongoDB进行CRUD操作的两种方式

    1 简介 Springboot是最简单的使用Spring的方式,而MongoDB是最流行的NoSQL数据库.两者在分布式.微服务架构中使用率极高,本文将用实例介绍如何在Springboot中整合Mon ...

  8. Springboot整合MongoDB的Docker开发,其它应用也类似

    1 前言 Docker是容器开发的事实标准,而Springboot是Java微服务常用框架,二者必然是会走到一起的.本文将讲解如何开发Springboot项目,把它做成Docker镜像,并运行起来. ...

  9. 8、SpringBoot整合之SpringBoot整合MongoDB

    SpringBoot整合MongoDB 一.创建项目,选择依赖 仅选择Spring Web.Spring Data MongoDB即可 二.引入相关依赖(非必要) 这里只是为了实体类的创建方便而引入l ...

随机推荐

  1. PTA(Advanced Level)1075.PAT Judge

    The ranklist of PAT is generated from the status list, which shows the scores of the submissions. Th ...

  2. redis 发布订阅、geo、bitmap、hyperloglog

    1.发布订阅 简介 发布订阅类似于广播功能.redis发布订阅包括 发布者.订阅者.Channel 命令 命令 作用 时间复杂度 subscribe channel 订阅一个频道 O(n) unsub ...

  3. Linux系列:进阶之tomcat安装

    思路:作者是在Windows上从Apache官网下载的tomcat,之后将tomcat文件放到我的ftp站点中,在Linux访问ftp站点下载tomcat文件 ,将tomcat放在我自己的安装目录中, ...

  4. 洛谷P2622 关灯问题II (二进制枚举+bfs

    题目描述 现有n盏灯,以及m个按钮.每个按钮可以同时控制这n盏灯——按下了第i个按钮,对于所有的灯都有一个效果.按下i按钮对于第j盏灯,是下面3中效果之一:如果a[i][j]为1,那么当这盏灯开了的时 ...

  5. STL string 常见用法详解

    string 常见用法详解 1. string 的定义 //定义string的方式跟基本数据类型相同,只需要在string后跟上变量名即可 string str; //如果要初始化,可以直接给stri ...

  6. 安装 pybloomfilter

    1.在windows的cmd下,使用 pip install pybloomfiltermmap 命令安装,pybloomfiltermmap 时报错 ,错误信息如下 根据错误信息分析,报错原因是需要 ...

  7. 如何修改maven本地仓库位置

    1.创建文件夹D:\m2\repository 2.修改E:\apache-maven-3.5.4\conf\setting.xml文件.将 改成<localRepository>< ...

  8. dgv数据绑定后,添加行遇到过的问题并解决

    1. 当控件被数据绑定时,无法以编程方式向 DataGridView 的行集合中添加行 解决方法:((DataTable)Dgv.DataSource).Rows.Add("", ...

  9. 关于SQL查询某年数据 和DATEPART 函数的使用

    数据库查询某年数据(sql server)select *from 表名 where YEAR(存时间的字段名) =某年select *from News where YEAR(addDate) =2 ...

  10. spring boot 使用RedisTemplate

    1导入包 <!-- redis --> <dependency> <groupId>org.springframework.boot</groupId> ...