springboot中mongodb自定义类型转换器

文章目录

1 场景

1.1 BigDecimal写入mongo

如在springboot中集成mongoDb,将使用mongoTemplate操作mongo数据库。

java中使用mongoTemplate面临一个问题, 向数据库写入数据时,如果java中映射的属性类型为BigDecimal,该属性映射到mongo中对应的的类型为String,显然这是不符合我们期待的。

会导致如下问题:

(1)查询排序将按照字符串排序,而不是按照数值排序

(2)大于、大于等于类似的数值查询方式,会受影响,仍然按照字符串进行匹配

原因是mongo不支持BigDecimal类似的科学计数法的类型,java客户端默认将BigDecimal类型转换成了String。

1.2 人工转换

当前有的研发,为了解决此问题,在java程序中人工手动做了转换,向mongo存储数据时,在程序中将每个数值类型由BigDecimal均转换为java中的Double类型。

此种情况,面临如下问题:

每个向数据库写插入或者更新数据时,均需要人工做数据类型的转换。如果漏掉了某次转换,mongo同一个表中的同一个字段出现不同类型(mongoDb允许此类存储方式),类型出现字符串和Double两种类型的情况,后期会导致很多不可预料的问题。

1.3 自定义转换器

mongo的数据类型支持浮点型的Double,mongo的java客户端可以自定义类型转换器。于是我们在spring整合mongo时,自定义mongo类型转换器。

达到如下效果:

(1)java程序向mongo写入数据时,BigDecimal自动转换成Double类型。

(2)java程序从mongo中读取数据时,Double类型自动转换成BigDecimal类型。

2 版本

**springBoot:**2.2.9.RELEASE

**mongodb:**4.2

3 步骤

3.1 定义转换器

BigDecimal转Double:

import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;

/**
 * mongo数字转换器(BigDecimal转Double)
 **/
@Component
@WritingConverter
public class BigDecimalToDoubleConverter implements Converter<BigDecimal, Double> {
    @Override
    public Double convert(BigDecimal source) {
        return source.doubleValue();
    }
}

Double转BigDecimal:

import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;

/**
 * mongo数字转换器(Double转BigDecimal)
 **/
@Component
@ReadingConverter
public class DoubleToBigDecimalConverter implements Converter<Double, BigDecimal> {
    @Override
    public BigDecimal convert(Double source) {
        return new BigDecimal(String.valueOf(source));
    }
}

3.2 配置mongoDb工厂类

@Bean
public MongoDbFactory mongoDbFactory(){
	......
}

mongoDb工厂配置,详细见文章:

springboot集成mongodb

3.3 加载自定义转换器

/**
 * 自定义转换器
 * @return org.springframework.data.mongodb.core.convert.CustomConversions
 */
@Bean
public CustomConversions customConversions() {
	List<Converter<?, ?>> converterList = new ArrayList<>();
	converterList.add(new BigDecimalToDoubleConverter());
	converterList.add(new DoubleToBigDecimalConverter());
	return new CustomConversions(converterList);
}

3.4 加载映射转换器

/**
 * mongo映射转换器
 * @param mongoDbFactory mongo工厂
 * @param mappingContext 映射命名空间
 * @param customConversions 自定义转换器
 * @return org.springframework.data.mongodb.core.convert.MappingMongoConverter 
 */
@Bean
public MappingMongoConverter mappingMongoConverter(MongoDbFactory mongoDbFactory, MongoMappingContext mappingContext, CustomConversions customConversions) {
	DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory);
	MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, mappingContext);
	//添加自定义的转换器
	mappingConverter.setCustomConversions(customConversions);
	//去掉默认mapper添加的_class
	//mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
	return mappingConverter;
}

3.5 配置mongo句柄

/**
 * 默认mongo句柄(写关注为SAFE)
 * @param mongoDbFactory mongo工厂
 * @param mappingMongoConverter 映射命名空间
 * @return org.springframework.data.mongodb.core.MongoTemplate 
 */
@Bean
public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, MappingMongoConverter mappingMongoConverter) {
	MongoTemplate mongoTemplate=new MongoTemplate(mongoDbFactory, mappingMongoConverter);
	mongoTemplate.setWriteConcern(WriteConcern.SAFE);
	return mongoTemplate;
}
上一篇:浅谈BigDecimal


下一篇:BigDecimal类