场景

  1. 当在springboot中集成MongoDB的时候,通常使用mongoTemplate操作db,而在不做任何操作的情况下,BigDecimal写入mongo会变成字符串的形式,这很显然不符合我们的预期,不管是在取值还是做排序。
  2. 另外一种情况就是存入时间的问题,因为mongo入库时间以UTC时间为标准,当将正常时间入库时因为东八区的问题会把时间减去8小时,导入入库时间不是我们想要看到的,当然这种方式可以通过手动转时间戳或者手动转换存取的时间格式。

以上这两种情况无论如果是手动处理每个实体则会导致操作变复杂,加大工作量,代码冗余,如果漏掉某次转换则会导致数据出现问题。

所以针对这种情况就可以通过自定义转换器实现。

自定义转换器

期望达到效果

  • 时间和时间戳在写入和取出时可以自动转换
  • BigDecimal和Decimal在写入和取出时可以自动转换

实现

mongo配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@Configuration
public class MongoConfig {
/**
* 自定义转换器
*
* @return org.springframework.data.mongodb.core.convert.CustomConversions
*/
@Bean
public MongoCustomConversions customConversions() {
List<Converter<?, ?>> converterList = new ArrayList<>();
converterList.add(new MgBigDecimalToDecimal128Converter());
converterList.add(new MgDecimal128ToBigDecimalConverter());
converterList.add(new MgLocalDateTimeToLongConverter());
converterList.add(new MgLongToLocalDateTimeConverter());
return new MongoCustomConversions(converterList);
}

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

转换器实现

LocalDatetime转时间戳

1
2
3
4
5
6
7
8
@Component
@WritingConverter
public class MgLocalDateTimeToLongConverter implements Converter<LocalDateTime, Long> {
@Override
public Long convert(LocalDateTime localDateTime) {
return localDateTime.toEpochSecond(ZoneOffset.of("+8"));
}
}

时间戳转LocalDateTime

1
2
3
4
5
6
7
8
@Component
@ReadingConverter
public class MgLongToLocalDateTimeConverter implements Converter<Long, LocalDateTime> {
@Override
public LocalDateTime convert(Long timestamp) {
return LocalDateTime.ofEpochSecond(timestamp, 0, ZoneOffset.of("+8"));
}
}

BigDecimal转Decimal128

1
2
3
4
5
6
7
8
@Component
@WritingConverter
public class MgBigDecimalToDecimal128Converter implements Converter<BigDecimal, Decimal128> {
@Override
public Decimal128 convert(BigDecimal bigDecimal) {
return new Decimal128(bigDecimal);
}
}

Decimal128转BigDecimal

1
2
3
4
5
6
7
8
@Component
@ReadingConverter
public class MgDecimal128ToBigDecimalConverter implements Converter<Decimal128, BigDecimal> {
@Override
public BigDecimal convert(Decimal128 decimal128) {
return decimal128.bigDecimalValue();
}
}

其他

再补充 下班了~~