SpringBoot+Mybatis,返回Map的时候,将Map内的Key转换为驼峰的命名表达式

碰见这个问题,是公司的小伙伴跟我说,每次使用mybatis的时候,简单的连表查询,用Map接收的时候,都是像DB定义的字段同样,相似如下 student_name,student_id,没有转换为驼峰,可是又不能由于这一个定义一个javabean来映射数据库字段集合,这样,会有无穷无尽的javabean,彻底不是办法,而后我看了下mybatis-spring-boot的配置文档http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/,发现有这么个属性  html

mybatis.configuration.map-underscore-to-camel-case=true

看着属性意思,很像是 map 下划线转换为驼峰,而后我天真的觉得,加个这个,就会将Map里面的key转换为驼峰的命名方式,而后我本身测试了一下,发现本身仍是太天真,没转过来,该是什么仍是什么(内心面是B了狗了)....java

没办法,接着找了了一下,发现官方文档http://www.mybatis.org/mybatis-3/configuration.html#properties,描述过这个的做用 spring

才发现,这个属性的做用,是做用于javabean的field的,并非map,ㄟ( ▔, ▔ )ㄏ,那没办法了,只能本身动手了数据库

 

 

-------------------------------我是分割线--------------------------------------apache

既然 map-underscore-to-camel-case 不能做用于map,那么只能本身动手了,而后我就想到了2个解决方案:session

  1. 继承HashMap,重写Put函数,将mybatis返回的Map,写上自定义Map的路径,自定义的Map,将全部的key内部转换为驼峰表达式
  2. 找到mybatis的Handler,经过Handler来找到转换映射关系的接口定义,继承或者实现接口,而后走自定义的转换规则来实现Map映射的驼峰转换

最终决定,采用第二种,方便之后扩展,以及项目结构mybatis

 

 

首先,我开始找mybatis的configuration里面的mapUnderscoreToCamelCase属性调用的地方app

 

有两个地方调用了,而后咱们看第一个调用的地方,发现名称是createAutomaticMappings,应该是map的映射字段建立没跑了,以下代码,光标显示的地方,就是调用的地方ide

 

而后咱们在查看属性传递进去后的操做,点进 metaObject.findProperty的实现函数

 

接着在看,objectWrapper.findProperty,发现是个接口,而后咱们须要查看,是对应的哪一个实现,而后我debug发现是 MapWrapper的实现,并无作任何操做,直接返回了name

 

到这里,我点开了下源码的目录结构,发现了如下

 

 

内心大概明白怎么回事了,具体过程应该以下

 

经过接口ObjectWrapper来定义行为,有默认的一些实现,而后经过工厂ObjectWrapperFactory接口,来建立ObjectWrapper接口,最后来进行对方的自动映射跟包装,自此,内心已经想到怎么改动了

 

 

--------------show code-----------------------

 

 

1.首先,咱们先继承类 MapWrapper,重写findProperty,经过useCamelCaseMapping来判断是否开启使用驼峰

public class CustomWrapper extends MapWrapper{
	
	
	public CustomWrapper(MetaObject metaObject, Map<String, Object> map) {
		super(metaObject, map);
	}
	
	
	@Override
	public String findProperty(String name, boolean useCamelCaseMapping) {
		if(useCamelCaseMapping){
            //CaseFormat是引用的 guava库,里面有转换驼峰的,省得本身重复造轮子,pom添加
            /**
             **         <dependency>
                           <groupId>com.google.guava</groupId>
                           <artifactId>guava</artifactId>
                           <version>24.1-jre</version>
                         </dependency>
             **/
			return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL,name);
		}
		return name;
	}
}

 

 2. 而后,咱们在实现接口 ObjectWrapperFactory,经过包装工厂来建立自定义的包装类,经过hasWrapperFor判断参数不为空,而且类型是Map的时候才使用本身扩展的ObjectWrapper

public class MapWrapperFactory implements ObjectWrapperFactory {
	
	@Override
	public boolean hasWrapperFor(Object object) {
		return object != null && object instanceof Map;
	}
	
	@Override
	public ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {
		return new CustomWrapper(metaObject,(Map)object);
	}
}

 

 3. 作完以上操做后,咱们须要替换下,之前默认的实现,恰好,mybatis-spring-boot上面有告诉咱们怎么作,返回一个 ConfigurationCustomizer 的bean,经过匿名内部类实现覆盖默认的MapWrapper的findProperty函数

@Configuration
public class MybatisConfig {
	
	@Bean
	public ConfigurationCustomizer mybatisConfigurationCustomizer(){
		return new ConfigurationCustomizer() {
			@Override
			public void customize(org.apache.ibatis.session.Configuration configuration) {
				configuration.setObjectWrapperFactory(new MapWrapperFactory());
			}
		};
	}
	
}

 

 

作了以上操做后,咱们就将默认的Map映射,的包装类,查找property的部分,变成了本身想要的样子,

最后,咱们在 properties或者yml里面加上 mybatis.configuration.map-underscore-to-camel-case=true ,毕竟在CustomerWrapper里面,咱们是经过使用这个来控制是否转换驼峰的,最后写个测试用例跑一下,而后会发现,之前db的字段,下划线已经转换成驼峰命名了

到这,文章就结束了!

以上,均为本人测试而得出的结果,可能会有出入,或者错误,欢迎指正

欢迎转载,请注明出处跟做者,谢谢!

相关文章
相关标签/搜索