每次使用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

Mybatis,返回Map的时候,将Map内的Key转换为驼峰的命名的更多相关文章

  1. Spring Boot将Mybatis返回结果转为驼峰的三种实现方式

    本文不再更新,可能存在内容过时的情况,实时更新请访问原地址:Spring Boot将Mybatis返回结果转为驼峰的三种实现方式: 我们通常获取Mybatis返回的数据结果时想要将字段以驼峰的形式返回 ...

  2. mybatis返回结果封装为map的探索

    需求 根据课程id 列表,查询每个课程id的总数,放到一个map里 最简单的就是循环遍历,每一个都查询一次网上说mybatis可以返回Map 和 List<Map>两种类型 尝试 直接返回 ...

  3. MyBatis 返回类型resultType为map时的null值不返回问题

    问题一:    查询结果集中 某字段 的值为null,在map中不包含该字段的key-value对 解决:在mybatis.xml中添加setting参数 <!-- 在null时也调用 sett ...

  4. mybatis返回map类型数据空值字段不显示的解决方法

    在日常开发中,查询数据返回类型为map,数据库中有些自动值为null,则返回的结果中没有值为空的字段,则如何显示值为空的字段呢? Spring boot + MyBatis返回map中null值默认不 ...

  5. mybatis返回map结果集

    今天突发奇想,想用mybatis返回一个map结果集,结果我就整了一下午,不过终于解决了 1.如果你确定返回的数据只有一条,你可以这样整 xml中: <select id="searc ...

  6. MyBatis返回map数据

    (1)接口中编写方法 //单行 public Map<String, Object> getEmpReturnMap(Integer id); //多行 @MapKey("id& ...

  7. MyBatis返回Map键值对数据

    List<Map<String, String>> getMtypeList(); <select id="getMtypeList" resultT ...

  8. mybatis 返回值类型是Map

    <select id="selectByMemberKey" resultType="java.util.HashMap"> SELECT memb ...

  9. mybatis异常:Improper inline parameter map format. Should be: #{propName,attr1=val1,attr2=val2}问题分析及解决

    转载自:http://blog.csdn.net/jackpk/article/details/44158701 mybatis异常:Improper inline parameter map for ...

随机推荐

  1. win10下通过npm成功搭建react开发环境

    1.安装node-v12.13.1-x64(LTS) 2.安装creatre-react-app: npm install -g create-react-app 3.通过create-react-a ...

  2. ireport初接触

    我用的版本5.6.0 @官网下载地址 下载安装@参考博客龙凌云端,着重留意:在windows下使用,只下载iReport-5.6.0-windows-installer.exe就行了 安装后配置环境变 ...

  3. plsql 记录型变量

    set serveroutput on declare emplist emp%rowtype; begin ; dbms_output.put_line(emplist.ename||'的薪水是'| ...

  4. [LeetCode] 555. Split Concatenated Strings 分割串联字符串

    Given a list of strings, you could concatenate these strings together into a loop, where for each st ...

  5. 【Tools】HP/惠普v285w 量产工具

    前段时间朋友说自己u盘坏了,让帮忙看看.看下图是这个u盘. 坏的问题:往里面复制东西,提示:请去掉写保护或使用另一张磁盘.但是能正常从里面读取出来数据. 无论更换电脑,还是使用网上的修改注册表等方式皆 ...

  6. Consul1.5.0 带ACL控制集群搭建

    Consul Cluster with ACL1.机器规划2.先配置好三个Server,并启动一遍.3.生成并配置agent-token,解决server agent ACL block问题4.启动一 ...

  7. PHPExcel 中文使用手册参数详解 三

    设置excel的属性:创建人$objPHPExcel->getProperties()->setCreator("Maarten Balliauw");最后修改人$ob ...

  8. Java线程 : 线程同步与锁

    一.同步问题提出 线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 例如:两个线程ThreadA.ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据. public ...

  9. 谈谈php里的IOC控制反转,DI依赖注入(转)

    转自:http://www.cnblogs.com/qq120848369/p/6129483.html 发现问题 在深入细节之前,需要确保我们理解"IOC控制反转"和" ...

  10. adb常用命令总结

    针对移动端 Android 的测试, adb 命令是很重要的一个点,必须将常用的 adb 命令熟记于心, 将会为 Android 测试带来很大的方便,其中很多命令将会用于自动化测试的脚本当中. And ...