前言

在开发过程中遇到以下情况,在mybatis中查询的结果集为Map类型,当我们需要将该map转换为实体类的时候,有以下两种方式:

  • 在sql中使用AS关键字,将所有字段设置别名为驼峰格式
<select id="getMember">
        select
            member_id as memberId,
            member_name as memberName
        from member;
</select>
  • 通过resultMap指定返回结果集
<resultMap id="MemberResult" type="java.util.Map">
            <result column="member_id" property="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
            <result column="member_name" property="orderNo" jdbcType="VARCHAR" javaType="java.lang.String"/>
</resultMap>
<select id="getMember" resultMap="MemberResult">
        select
            member_id as memberId,
            member_name as memberName
        from member;
</select>

通过以上两种方式我们取得的Map结果集,就可以通过jackson或者fastjson来转换成实体类了

	//使用jackson将map转为实体类
	ObjectMapper mapper = new ObjectMapper();
        User user = mapper.convertValue(map, User.class);
        //使用fastjson将map转为实体类
        User user = JSON.parseObject(JSON.toJSONString(map), User.class);

上面的方式确实是解决了下划线命名的方式转实体类的功能,但是并未从根本上解决问题,我们还是需要将数据库中下划线的字段手动转换为实体类所需的驼峰式命名,为了解决这个问题,手动撸了一个下划线命名转驼峰命名的工具,并转换为实体类。下面直接上代码:

实现

实现思路:遍历map,并将下划线命名的key转换为驼峰式命名

import java.lang.reflect.Field;
import java.util.Map;
 public class MapUtil {
    /**
     * 将下划线命名的字符串转换为驼峰式命名
     *
     * @param underlineStr 下划线命名的字符串
     * @return 驼峰式命名的字符串
     */
    private static String underlineToCamel(String underlineStr) {
        StringBuilder camelBuilder = new StringBuilder();
        boolean nextUpperCase = false;
        for (int i = 0; i < underlineStr.length(); i++) {
            char c = underlineStr.charAt(i);
            if (c == '_') {
                nextUpperCase = true;
            } else {
                if (nextUpperCase) {
                    camelBuilder.append(Character.toUpperCase(c));
                    nextUpperCase = false;
                } else {
                    camelBuilder.append(c);
                }
            }
        }
        return camelBuilder.toString();
    }
     /**
     * 将Map中的数据转换为指定类型的对象
     *
     * @param map   待转换的Map
     * @param clazz 指定类型的Class
     * @return 转换后的指定类型的对象
     * @throws Exception 转换过程中出现的异常
     */
    public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz) throws Exception {
        T bean = clazz.newInstance();
        for (String key : map.keySet()) {
            Object value = map.get(key);
            try {
                Field field = clazz.getDeclaredField(key);
                field.setAccessible(true);
                field.set(bean, value);
            } catch (NoSuchFieldException e) {
                //如果bean中没有这个属性,则忽略该字段
            }
        }
        return bean;
    }
     /**
     * 将下划线命名的Map转换为驼峰式命名的指定类型的对象
     *
     * @param map   下划线命名的Map
     * @param clazz 指定类型的Class
     * @return 驼峰式命名的指定类型的对象
     * @throws Exception 转换过程中出现的异常
     */
    public static <T> T convertToCamelCase(Map<String, Object> map, Class<T> clazz) throws Exception {
        Map<String, Object> camelMap = new HashMap<>();
        for (String key : map.keySet()) {
            camelMap.put(underlineToCamel(key), map.get(key));
        }
        T result = clazz.newInstance();
        result = mapToBean(camelMap, clazz);
        return result;
    }
}

测试

import java.util.HashMap;
import java.util.Map;

public class Test {
    public static void main(String[] args) throws Exception {
        Map<String, Object> map = new HashMap<>();
        map.put("user_name", "Tom");
        User user = MapUtil.convertToCamelCase(map, User.class);
        System.out.println(user.getUserName()); // 输出 "Tom"
    }
}

class User {
    private String userName;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

这个测试用例中,我们使用 MapUtil.convertToCamelCase 方法将下划线命名的 map 转换为驼峰式命名的 User 类型的对象 user 。然后输出了 user 的 userName 属性,预期输出结果应该是 “Tom” 。