springboot整合mongodb问题1-Decimal128和BigDecimal的转换之mongodb转换器使用(转)

转自: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

原文地址:https://www.cnblogs.com/muxi0407/p/11703316.html

时间: 2024-08-29 23:06:25

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

springboot整合mybatis,mongodb,redis

springboot整合常用的第三方框架,mybatis,mongodb,redis mybatis,采用xml编写sql语句 mongodb,对MongoTemplate进行了封装 redis,对redisTemplate进行封装成工具类 可以基于该项目进行快速开发,省得以后每次开发又要重新整合一遍 项目结构: 属性配置文件 mybatis.mapper-locations=classpath*:/mapper/**/*.xml mybatis.type-aliases-package=com

springboot 整合 MongoDB 实现登录注册,html 页面获取后台参数的方法

springboot简介: Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者. MongoDB的简介: MongoDB 是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据

springboot整合drui、mybatis、pagehelper

springboot配置数据连接池druid Druid是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池. 在功能.性能.扩展性方面,都超过其他数据库连接池,同时加入了日志监控, 可以很好的监控DB池连接和SQL的执行情况 配置pom依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactI

springboot整合mybatis实现逆向工程

springboot整合mybatis创建逆向工程,快速的创建pojo实体,dao接口,mapper xml文件 第一步添加依赖 <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 htt

SpringBoot整合dubbo(yml格式配置)

yml文件 如果只作为服务的消费者不用暴露端口号,扫描的包名根据自己service改 dubbo: application: name: springboot-dubbo-demo #应用名 registry: address: zookeeper://127.0.0.1:2181 #zookeeper地址 # port: 2181 #提供注册的端口 protocol: name: dubbo port: "20889" #dubbo服务暴露的端口 scan: com.bw.ssm.s

SpringBoot 2.SpringBoot整合Mybatis

一.创建Springboot的配置文件:application.properties SpringApplication 会从 application.properties 文件中加载配置信息,下面是添加Spring配置信息的文件目录顺序: 当前目录下的/config子目录中 当前目录中 一个 classpath 包下的 /config 目录中 classpath 根目录中 大家根据自己习惯来即可. /application.properties 文件配置如下: spring.datasourc

springboot学习笔记-6 springboot整合RabbitMQ

一 RabbitMQ的介绍 RabbitMQ是消息中间件的一种,消息中间件即分布式系统中完成消息的发送和接收的基础软件.这些软件有很多,包括ActiveMQ(apache公司的),RocketMQ(阿里巴巴公司的,现已经转让给apache). 消息中间件的工作过程可以用生产者消费者模型来表示.即,生产者不断的向消息队列发送信息,而消费者从消息队列中消费信息.具体过程如下: 从上图可看出,对于消息队列来说,生产者,消息队列,消费者是最重要的三个概念,生产者发消息到消息队列中去,消费者监听指定的消息

SpringBoot整合Quartz定时任务

记录一个SpringBoot 整合 Quartz 的Demo实例 POM.XML文件 <!-- 定时器任务 quartz需要导入的坐标 --> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>1.8.5</version> </dependency> 类似于控制

springboot系列-springboot整合RabbitMQ

一 RabbitMQ的介绍 RabbitMQ是消息中间件的一种,消息中间件即分布式系统中完成消息的发送和接收的基础软件.这些软件有很多,包括ActiveMQ(apache公司的),RocketMQ(阿里巴巴公司的,现已经转让给apache). 消息中间件的工作过程可以用生产者消费者模型来表示.即,生产者不断的向消息队列发送信息,而消费者从消息队列中消费信息.具体过程如下: 从上图可看出,对于消息队列来说,生产者,消息队列,消费者是最重要的三个概念,生产者发消息到消息队列中去,消费者监听指定的消息