转自: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. sql常用到的查询连接

    一.内连接(Inner Join) select * from a inner join b on a.name=b.name; 此语句的结果为同时匹配表a和表b的记录集.即内连接取的是两个表的交集. ...

  2. 二叉树(Java实现)

    一.常见用语 1.逻辑结构:描述数据之间逻辑上的相关关系.分为线性结构(如,字符串),和非线性结构(如,树,图). 2.物理结构:描述数据的存储结构,分为顺序结构(如,数组)和链式结构. 3.结点的度 ...

  3. 虚拟机(Vmware)安装ubuntu18.04和配置调整(一)

    一.虚拟机(Vmware)安装ubuntu18.04 1.下载ubuntu18.04桌面版镜像文件< ubuntu-18.04.3-desktop-amd64.iso> 2.使用VMwar ...

  4. Java开源网页抓取工具httpClient以及jsoup

    网上看到不错的Java网页抓取工具和库 先记录一下 使用java开源工具httpClient及jsoup抓取解析网页数据

  5. jQuert DOM操作

    DOM操作 1 内部插入 append(content|fn) 向每个匹配的元素内部追加内容 appendTo(content) 把所有匹配的元素追加到另一个指定的元素元素集合中 prepend(co ...

  6. Jmeter之cookie登录

    1.在web登录时,抓取登录的响应头 2.在jmeter中配置cookie HTTP Cookie管理器中添加信息 以下三个字段是必填的 3.添加HTTP请求(直接访问首页) 如果返回成功,并且响应内 ...

  7. luogu P2765 魔术球问题 (最小路径覆盖)

    大意:给定n根柱子, 依次放入1,2,3,...的球, 同一根柱子相邻两个球和为完全平方数, 求最多放多少个球. 对和为平方数的点连边, 就相当于求DAG上最小路径覆盖. #include <i ...

  8. 怎样安装 cnpm 并切换到淘宝镜像?

    如果不使用 vpn , 在国内直接使用 npm 的官方镜像会很慢,这里推荐使用淘宝 NPM 镜像.淘宝 NPM 镜像是一个完整的 npmjs.org 镜像,可以用此代替官方版本(只读). 操作方法如下 ...

  9. Eclipse怎么升级版本

    java工程上右键——选择Properties——Project Faces——右边java项选择相应的版本就OK了

  10. TCP/IP协议栈各个层次及分别的功能

    网络接口层:这是协议栈的最低层,对应OSI的物理层和数据链路层,主要完成数据帧的实际发送和接收.网络层:处理分组在网络中的活动,例如路由选择和转发等,这一层主要包括IP协议.ARP.ICMP协议等.传 ...