mybatis Map查询结果下划线转驼峰的实例

添加一个配置类MybatisCamelConfig 即可

package com.fpi.notify.config;

import com.google.common.base.CaseFormat;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.wrapper.MapWrapper;
import org.apache.ibatis.reflection.wrapper.ObjectWrapper;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Map;

/**
 * mybatis查询Map返回值下划线转峰坨
 * @author xingxing_yuan
 * @since 2020-02-18 13:47
 */
@Configuration
public class MybatisCamelConfig {
 @Bean
 public ConfigurationCustomizer mybatisConfigurationCustomizer() {
//   使用自定义的解析器工厂
  return configuration -> configuration.setObjectWrapperFactory(new MapWrapperFactory());
 }

 /**
  * 实现工厂
  */
 static class MapWrapperFactory implements ObjectWrapperFactory {
  @Override
  public boolean hasWrapperFor(Object object) {
//  判断是Map就使用该解析
   return object instanceof Map;
  }

  @Override
  public ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {
//  将默认的解析器替换成峰坨转换
   return new CamelWrapper(metaObject, (Map) object);
  }
 }

 /**
  * 重写转换器;添加转换方法
  */
 static class CamelWrapper extends MapWrapper {

  CamelWrapper(MetaObject metaObject, Map<String, Object> map) {
   super(metaObject, map);
  }

  /**
   * mybatis查询结果下划线转峰坨
   *
   * @param name
   * @param useCamelCaseMapping 是否进行转换。yaml 中配置map-underscore-to-camel-case=true
   * @return
   */
  @Override
  public String findProperty(String name, boolean useCamelCaseMapping) {
   if (useCamelCaseMapping) {
//    使用guava的转换方法,覆盖Map的默认返回值
    return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name);
   }
   return name;
  }

 }
}

补充知识:关于Springboot+Mybatis中返回结果集为Map时其内的Key转换为驼峰的命名(2种方法)

使用场景:

使用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转换为驼峰的命名方式, 总归是太天真了。没办法,接着找了了一下,发现官方文档http://www.mybatis.org/mybatis-3/configuration.html#properties, 描述过这个的作用, 如下

才发现,这个属性的作用,是作用于javabean的field的,并不是map。既然 map-underscore-to-camel-case 不能作用于map,那么只能自己动手了,然后就想到了2个解决方案:

继承HashMap,重写Put函数,将mybatis返回的Map,写上自定义Map的路径,自定义的Map,将所有的key内部转换为驼峰表达式

找到mybatis的Handler,通过Handler来找到转换映射关系的接口定义,继承或者实现接口,然后走自定义的转换规则来实现Map映射的驼峰转换

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

下面是使用第二种的两种在项目中的具体实现

第一种实现方法:

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

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

然后我们在查看属性传递进去后的操作,点进 metaObject.findProperty的实现

接着在看,objectWrapper.findProperty,发现是个接口,然后我们需要查看,是对应的哪个实现,然后我debug发现是 MapWrapper的实现,并没有做任何操作,直接返回了name。

到这里,我们可以看下源码的目录结构,发现了以下

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

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

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的字段,下划线已经转换成驼峰命名了。

第二种实现方法:

这种方法就比较投机取巧了, 但是可以很简单的实现Map集合的映射,下面我们来具体看看实现过程。(PS: 推荐使用第一种方法吧, 比较官方!)

1.首先mybatis-3.4.5.jar中一个MapWrapper类, 现在我把这个MapWrapper类直接复制一份,然后创建相应的包, 这个包路径跟在jar包中的包路径完全一样的(位于根路径下的: ), 然后将复制的该MapWrapper文件直接粘贴至该包下, 那么这个就是我们自己的MapWrapper类。

2.对默认的Map映射的包装类查找property的findProperty方法进行改造,加入自己的映射转换规则, 当然也可以像第一种方法中一样: “引用的 guava库,里面有转换驼峰的,免得自己重复造轮子,pom添加依赖即可。” 这里我们自己尝试的实现, 代码如下:

@Override
 public String findProperty(String name, boolean useCamelCaseMapping) {
 if (useCamelCaseMapping
    && ((name.charAt(0) >= 'A' && name.charAt(0) <= 'Z')
     || name.indexOf("_") >= 0)) {
   return underlineToCamelhump(name);
  }
  return name;
 }
 private String underlineToCamelhump(String inputString) {
  StringBuilder sb = new StringBuilder();
  boolean nextUpperCase = false;
  for (int i = 0; i < inputString.length(); i++) {
   char c = inputString.charAt(i);
   if (c == '_') {
    if (sb.length() > 0) {
     nextUpperCase = true;
    }
   } else {
    if (nextUpperCase) {
     sb.append(Character.toUpperCase(c));
     nextUpperCase = false;
    } else {
     sb.append(Character.toLowerCase(c));
    }
   }
  }
  return sb.toString();
 }

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

最后, 我们同样在Mybatis配置文件中添加了如下配置:

毕竟在CustomerWrapper里面,我们是通过使用这个来控制是否转换驼峰的。

当然最主要可以这样实现的原因还是基于类加载机制允许的基础上的,了解过相应的类加载原理及加载顺序后我们可以知道:“位于WEB-INF目录下自定义的class类优先与该目录下的lib下jar包中的类加载; 同一个JVM里面,判断两个类是否相同的依据是类的全路径名称和类加载器名称是否完全相同。

但由于委派机制的存在,每个类只要在父类加载器哪里被找到,子类加载器就不会再尝试加载了,因此,同名的类只能被加载一次,这被称为单一原则。”

以上这篇mybatis Map查询结果下划线转驼峰的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • mybatisplus解决驼峰命名映射问题详解

    问题的提出 今天我在测试mybatis的时候,发现查询出来的一些字段为null,而且这些字段都是驼峰命名了的.所以我首先就想到了是数据库表字段和类映射出了问题. 解决办法 一.理解spring-mybatis.xml中关于驼峰命名的配置 mybatisplus是mybatis的升级版,所以配置还是有点儿差别,如果是mybatis的话,直接在configuration中配置就行了,如下: <?xml version="1.0" encoding="UTF-8"?

  • 为什么rest接口返回json建议采用下划线形式,不要用驼峰

    今天被数据大神说了,对接第三方接口返回的json字段我想用驼峰形式,他说我这样不专业.所以就改了,认怂. 记住以后再次对接rest接口,返回的字段用下划线形式 记录一下改的内容 1.使用fastjson的@JSONField(name = "is_member") 如果没有fastjson的包,要先引入 <!-- fastjson start --> <dependency> <groupId>com.alibaba</groupId>

  • Mybatis返回结果封装map过程解析

    需求 根据课程id 列表,查询每个课程id的总数,放到一个map里 最简单的就是循环遍历,每一个都查询一次 网上说mybatis可以返回Map 和 List<Map>两种类型 尝试 直接返回Map类型 <select id="listLessonSumByCourseIdList" resultType="java.util.HashMap"> SELECT course_id, count(1) FROM lesson WHERE stat

  • mybatis Map查询结果下划线转驼峰的实例

    添加一个配置类MybatisCamelConfig 即可 package com.fpi.notify.config; import com.google.common.base.CaseFormat; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.wrapper.MapWrapper; import org.apache.ibatis.reflection.wrapper.

  • Mybatis无法获取带有下划线前缀的字段的值问题

    目录 Mybatis无法获取带有下划线前缀的字段的值 打了断点,发现真相在这里 解决办法 Mybatis无法给带有下划线属性赋值 1.配置问题 2.增加set方法转换值的方式 Mybatis无法获取带有下划线前缀的字段的值 今天下面,把几张表里的字段都加了前缀,如 article_id,article_title,acticle_content,article_status. 然后通过Mybatis-generator 生成了 po和mapper,替换后. 原本正常的网页,这下数据全没了.当时,

  • 解决mybatis无法给带有下划线属性赋值问题

    目录 mybatis无法给带有下划线属性赋值问 1.配置问题 2.增加set方法转换值的方式 解决方法 实体类中有下滑线字段无法赋值问题 mybatis无法给带有下划线属性赋值问 1.配置问题 <!-- 是否开启自动驼峰命名规则(camel case)映射, --> <setting name="mapUnderscoreToCamelCase" value="true"/> 或者 //开启驼峰映射         bean.getObjec

  • js下划线和驼峰互相转换的实现(多种方法)

    目录 应用场景: 方法一:正则表达式 (推荐) 方法二:利用数组的 reduce 方法实现 方法三:利用数组的 map 方法实现 JS字符串的下划线命名和驼峰命名转换 应用场景: 有时候传给后端的参数是驼峰命名,回显的时候是下划线,这个时候就需要修改key值 方法一:正则表达式 (推荐) 驼峰式转下横线: function toLowerLine(str) { var temp = str.replace(/[A-Z]/g, function (match) { return "_"

  • Go语言json编码驼峰转下划线、下划线转驼峰的实现

    一.需求 golang默认的结构体json转码出来,都是根据字段名生成的大写驼峰格式,但是一般我们最常用的json格式是小写驼峰或者小写下划线,因此,我们非常需要一个统一的方法去转换,而不想挨个写json标签,例如 package main import ( "encoding/json" "fmt" ) func main() { type Person struct { HelloWold string LightWeightBaby string } var

  • SQL查询包含下划线的字段内容操作

    我就废话不多说了,大家还是直接看代码吧~ SELECT * FROM scott.emp where ename like '%\_%' escape '\'; SELECT * FROM scott.emp where regexp_like (ename,'_'); 补充:sql 字符带下划线匹配问题 SQL 中 _下划线 作用是 匹配一个任意字符. 如果我们要去掉下划线的作用 单纯只用作一个字符则需要转义成  like '%\_%' escape '\' 字段 1.order_qrsc 2

  • FastJson实现驼峰下划线相互转换方法详解

    目录 PropertyNamingStrategy 发挥作用的是translate方法 指定反序列化格式 智能匹配功能 fastjson智能匹配处理过程 关闭智能匹配的情况 PropertyNamingStrategy 有四种序列化方式. CamelCase策略,Java对象属性:personId,序列化后属性:persionId – 实际只改了首字母 大写变小写 PascalCase策略,Java对象属性:personId,序列化后属性:PersonId – 实际只改了首字母 小写变大写 Sn

  • java中驼峰与下划线的写法互转

    前言 在实际项目开发中,会碰到这样的问题,数据库表结构设计好了,可实体类还没相应地弄出来.实体类的属性命名方法一般是驼峰法,而数据库中的表字段命名方法用的是下划线法.如果表的字段非常多,我们根据设计好的数据库字段再手动敲写一遍驼峰法的属性,这有点费时了.如何迅速地把数据库中的表字段变成我们所需要的驼峰式的属性呢? 解决方法有二,一是通过文本编辑工具,如EditPlus,Notepad++等,利用它们携带的正则替换功能来迅速实现:二是通过自己编写工具类来实现.至于第一种方法操作技巧,不在这边赘述.

  • Java实现驼峰和下划线互相转换的示例代码

    目录 前言 1.驼峰与下划线互转 2.测试 3.方法补充 前言 基本语法 首先我们要知道java的基础语法. 1.由26个英文字母大小写,0-9,_或$组成 2.数字不可以开头 3.不可以使用关键字和保留字,但是能包括关键字和保留字 4.Java中严格区分大小写,长度无限制 5.标识符不能包括空格 6.取名尽量做到“见名知意” 驼峰命名法 骆驼式命名法(Camel-Case)又称驼峰式命名法,是电脑程式编写时的一套命名规则(惯例). 正如它的名称CamelCase所表示的那样,是指混合使用大小写

  • 为spring get请求添加自定义的参数处理操作(如下划线转驼峰)

    1.生成自己的注解(为了确定在哪些位置使用) /** * 关闭patch delete的model处理,否则会报错 */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AliasProcessor { } /** * 处理Get 请求参数的驼峰问题 * @author lw */ @Target(ElementType.FIELD) @Retentio

随机推荐