zoukankan      html  css  js  c++  java
  • 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/,发现有这么个属性  

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

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

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

    才发现,这个属性的作用,是作用于javabean的field的,并不是map,ㄟ( ▔, ▔ )ㄏ,那没办法了,只能自己动手了。

    既然 map-underscore-to-camel-case 不能作用于map,那么只能自己动手了,然后我就想到了2个解决方案:

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

    最终决定,采用第二种,方便以后扩展。

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

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

    然后我们在查看属性传递进去后的操作,点进 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的字段,下划线已经转换成驼峰命名了

    到这,文章就结束了!

    转自:https://my.oschina.net/u/2278977/blog/1795969

  • 相关阅读:
    jar包依赖整理(一)
    centos 下 tomcat 内存不足引起的错误
    KendoUI 基础:Grid 绑定template展示
    C#读取XML文件的五个步骤
    C#winform向Txt文件传值,不重复录入且不清空
    JS页面赋值
    Python3---对象编程思想
    Python3---标准库---numpy
    Python3---标准库json
    Python3---标准库sys
  • 原文地址:https://www.cnblogs.com/panchanggui/p/10919453.html
Copyright © 2011-2022 走看看