spring boot+mybatis查询结果为map的时候将key转换为驼峰形式方法

        前言:项目使用springboot+mybatis搭建,在一些联表查询中使用了Map集合来接收结果,不过发现返回的结果中key都是和数据库列名一样:带有下划线很不方便,记得官方文档上有个驼峰转换的配置 map-underscore-to-camel-case , 于是想当然的以为加上就ok了,测试后发现接收为对象实体的时候确实是可以转换为驼峰形式,但是map集合还是不起作用。

        于是想到从源码入手,先理清 map-underscore-to-camel-case是怎么运行的,首先在配置文件中增加如上配置,然后点击进入源码发现mybatis将配置文件中的值读取赋值给自己的属性mapUnderscoreToCamelCase

        然后点击属性mapUnderscoreToCamelCase,查看有哪些地方进行了引用,发现有个DefaultResultSetHandler.java调用MetaObject中findProperty方法使用到了这个属性:

       接着点击 findProperty 方法,发现 ObjectWrapper 是一个接口,这样我们就需要查看是哪个类进行了实现,通过 debug 发现是MapWrapper BeanWrapper 两个类进行了实现,前者没有做任何处理直接返回了name后者判断如果配置为true的话将返回的列名toUppercase后和通过反射获得的对象属性进行比对,如果比对上了就返回属性名(这也就解释了为什么结果为实体bean的时候会进行转换,map没有转换的原因):

BeanWrapper.java
@Override
  public String findProperty(String name, boolean useCamelCaseMapping) {
    return metaClass.findProperty(name, useCamelCaseMapping);
  }

MetaClass.java
public String findProperty(String name, boolean useCamelCaseMapping) {
    if (useCamelCaseMapping) {
      name = name.replace("_", "");
    }
    return findProperty(name);
  }

public String findProperty(String name) {
    StringBuilder prop = buildProperty(name, new StringBuilder());
    return prop.length() > 0 ? prop.toString() : null;
  }
private StringBuilder buildProperty(String name, StringBuilder builder) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      String propertyName = reflector.findPropertyName(prop.getName());
      if (propertyName != null) {
        builder.append(propertyName);
        builder.append(".");
        MetaClass metaProp = metaClassForProperty(propertyName);
        metaProp.buildProperty(prop.getChildren(), builder);
      }
    } else {
      String propertyName = reflector.findPropertyName(name);
      if (propertyName != null) {
        builder.append(propertyName);
      }
    }
    return builder;
  }

Reflector.java
/**
 *在初始化Reflector的时候根据反射机制将指定class的所有属性获取并全部转成大写保存到下面的caseInsensitivePropertyMap集合里,这里进行get操作并返回
 */
public String findPropertyName(String name) {
    return caseInsensitivePropertyMap.get(name.toUpperCase(Locale.ENGLISH));
  }

        看到这里已经很清楚怎么改了:

        1、我们需要自定义 wrappe r继承 MapWrapper 类并重写它的 findProperty 方法,通过userCamelCaseMapping参数判断是否需要进行驼峰处理。

package com.sailing.yjbj.config.wrapper;

import com.google.common.base.CaseFormat;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.wrapper.MapWrapper;

import java.util.Map;

/**
 * @author baibing
 * @project: iemp-yjbj
 * @package: com.sailing.yjbj.config.wrapper
 * @Description: 自定义wrapper处理spring boot + mybatis返回结果为map时的key值转换为驼峰
 * @date 2018/11/1 11:34
 */
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){
            return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL,name);
        }
        return name;
    }
}

        2、同时也要实现 ObjectWrapperFactory 工厂接口,判断如果所传对象为Map类型的时候,才将自定义的 wrapper 处理器返回并使用。

package com.sailing.yjbj.config.wrapper;

import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.wrapper.ObjectWrapper;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;

import java.util.Map;

/**
 * @author baibing
 * @project: iemp-yjbj
 * @package: com.sailing.yjbj.config.wrapper
 * @Description: 实现接口 ObjectWrapperFactory,通过包装工厂来创建自定义的wrapper
 * @date 2018/11/1 11:38
 */
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、最后需要替换原来默认的实现,mybaits文档上告诉了我们怎么做,返回一个 ConfigurationCustomizer ,通过匿名内部类将自己的实现工厂set进去即可:

package com.sailing.yjbj.config;

import com.sailing.yjbj.config.wrapper.MapWrapperFactory;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author baibing
 * @project: iemp-yjbj
 * @package: com.sailing.yjbj.config
 * @Description: mybatis配置类,将自定义的MapWrapperFactory覆盖默认的ObjectWrapperFactory
 * @date 2018/11/1 11:42
 */
@Configuration
public class MybatisConfig {

    @Bean
    public ConfigurationCustomizer mybatisConfigurationCustomizer(){
        System.out.println("initiazing ConfigurationCustomizer....");
        return new ConfigurationCustomizer() {
            @Override
            public void customize(org.apache.ibatis.session.Configuration configuration) {
                configuration.setObjectWrapperFactory(new MapWrapperFactory());
            }
        };
    }
}

        4、驼峰转换的时候使用了google的guava库,maven依赖为:

<!-- 引用的 guava库,里面有转换驼峰的-->
		<dependency>
			<groupId>com.google.guava</groupId>
			<artifactId>guava</artifactId>
			<version>24.1-jre</version>
		</dependency>

        最后:通过测试返回的 Map 的时候成功进行了驼峰处理~~~~

项目下载地址:https://download.csdn.net/download/white_ice/10778916

因csdn后台会自动修改积分,导致现在积分较高,可以去下面地址免费下载:https://github.com/KingOfMonkey/springboot-mybatis ,喜欢的给个star。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值