Spring Boot + Spring Data MongoDB 中,MongoRepository方式,自定义 field-naming-strategy,域的名称映射方式

Spring Boot + Spring Data MongoDB 中,MongoRepository方式,自定义 field-naming-strategy,域的名称映射方式

(可直接翻至第五条看解决方案!)

1. 背景

一个Spring Boot + MongoDB +PostgreSQL 的项目

MongoDB:存了一些外部的现有数据,需要拿来做CRUD,但是这些数据命名不规范

  • Database的名字: snake_lower_case + snake_Upper_Case + snake_CamelCase 混合
  • Collection & Field的名字: UPPER_CASE

看了下外部模块代码(C++)挺多的,都是按这种名字写死在代码里的,这又不能让人家改。。(一个尴尬又不失礼貌的微笑.jpg)

2.所用依赖

之前用过MongoDB Java Driver,太基础了,这次用一个对懒人更友好,和spring boot 集成更好的

具体用的是MongoRepository,更死板,约定性非常强,但…jpa真香!
pom.xml部分信息如下

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
    <version>2.1.2.RELEASE</version>
</dependency>
3.相关代码(已做简化)
@Document(collection = "AREAL_STRUCT_MANAGEMENT")//这一句补充说明一下,可以解决类名和数据库名不同的问题
public class  ArealStructManagement {
    @Id
    private ObjectId id;
    private String name;
    private String namingTest;
}

mongoDB数据大概长这样

{
"_id":ObjectId("..."),
"NAME":"wine",
"NAMING_TEST":"OK?"
}
4.问题

在application.properties里面配置了:

spring.data.mongodb.field-naming-strategy=org.springframework.data.mapping.model.SnakeCaseFieldNamingStrategy

只解决了一部分问题,把nameTest换成了name_Test…也是个混合命名,所以这个配置项真的有用吗。。

Spring只提供了几个命名方式,都不满足需求

所以到底怎么把我写的类中的成员变量名字,在插入/查询数据库的时候自动改成另一种格式??

找了半天资料,找到了自定义的方法。

5.解决方案

在配置文件里声明一个Bean,进行自定义设置,这个地方还能解决插入的数据带_class的问题,具体方案请参阅其他博客

//配置文件
@Configuration
@EnableMongoRepositories(basePackageClasses = ArealStructManagementDao.class) 
public class MongoConfig extends AbstractMongoConfiguration {
    @Bean
    public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context, BeanFactory beanFactory) {
    //这句解决问题
    	context.setFieldNamingStrategy(new UpperCaseWithUnderscoreFieldNamingStrategy());
    }
}

然后随便找个地方写一个自己的映射策略

//自定义策略,目的:myName -> MY_NAME
//写的比较糙,可以优化,把delimiter当成参数,参考FieldNamingStrategy的其他实现
public class UpperCaseWithUnderscoreFieldNamingStrategy implements FieldNamingStrategy{
    @Override
    public String getFieldName(PersistentProperty<?> property) {
    	//有现成的工具,何乐不为
        List<String> parts= ParsingUtils.splitCamelCaseToLower(property.getName());
        StringBuilder sb=new StringBuilder();
        Iterator it=parts.iterator();
        if(it.hasNext()){
            sb.append(it.next().toString().toUpperCase());//按需要,转成大写。
            while (it.hasNext()){
                sb.append("_");
                sb.append(it.next().toString().toUpperCase());//按需要,转成大写。
            }
        }
        return sb.toString();
    }
}

这样改完之后,测试插入和查询的名字都OK,问题解决!

后记

安利一个新接触的依赖lombok,以前对这种不感兴趣的,现在发现还真是方便,可以省去大部分getter setter constructor的编写,支持链式set

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.6</version>
    <scope>provided</scope>
</dependency>
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值