利用java反射简化编码过程

最近工作接触一个java项目,项目没有使用mybatis等这类层久层,直接用的spring内置的连接池,所以就会有很多从数据库查找结果转转成DTO的函数,查找的结果集是一个Map对象如:

List<Map<String, Object>> resultList = executeJdbcQuery(sql, paramMap);

resultList结果需要保存为对象

public class ArticleKindResponse {
    private Long kindId;
    private String name;
    private String shortName;
    private String createTime;
    private Integer status;
   
    ...
}

所以代码里有很多类似这样的代码:

private ArticleKindResponse constructArticleKindResponse(Map<String, Object> map){ 
      ArticleKindResponse kind = new ArticleKindResponse();
      kind.setKindId(map.get("kind_id") == null ? null : Long.valueOf(map.get("kind_id").toString()));
      kind.setName(map.get("name") == null ? null : map.get("name").toString());
      kind.setShortName(map.get("short_name") == null ? null : map.get("short_name").toString());
      kind.setStatus(map.get("status") == null ? null : Integer.valueOf(map.get("status").toString()));
      kind.setCreateTime(map.get("create_time") == null ? null : map.get("create_time").toString());
      return kind;
}

每一个DTO都有一个类似的方法,简直不能忍。所以此刻想到用反射去改造它:

改造的前提:

  1. DTO的命名规范采用驼峰形式,基本数据类型为装箱类型
  2. 数据库字段命名全为小写字体,并用下划线连接

改造如下:

 protected <T> T constructObject(Map<String, Object> map, Class<T> clazz) throws DaoException {
        try {
            T obj = clazz.newInstance();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                String key = StringUtil.toCamelUnderline(field.getName());
                String type = field.getType().getName();
                if (type.equals("java.lang.String")) {
                    String value = map.get(key) == null ? null : map.get(key).toString();
                    if (value != null) field.set(obj, value);
                } else if (type.equals("java.lang.Integer")) {
                    Integer value = map.get(key) == null ? null : Integer.valueOf(map.get(key).toString());
                    if (value != null) field.set(obj, value);
                } else if (type.equals("java.lang.Long")) {
                    Long value = map.get(key) == null ? null : Long.valueOf(map.get(key).toString());
                    if (value != null) field.set(obj, value);
                } else if (type.equals("java.lang.Double")) {
                    Double value = map.get(key) == null ? null : Double.valueOf(map.get(key).toString());
                    if (value != null) field.set(obj, value);
                } else if (type.equals("java.lang.Float")) {
                    Float value = map.get(key) == null ? null : Float.valueOf(map.get(key).toString());
                    if (value != null) field.set(obj, value);
                } else if (type.equals("java.lang.Short")) {
                    Short value = map.get(key) == null ? null : Short.valueOf(map.get(key).toString());
                    if (value != null) field.set(obj, value);
                } else if (type.equals("java.lang.Byte")) {
                    Byte value = map.get(key) == null ? null : Byte.valueOf(map.get(key).toString());
                    if (value != null) field.set(obj, value);
                } else if (type.equals("java.lang.Character")) {
                    Character value = map.get(key) == null ? null : map.get(key).toString().charAt(0);
                    if (value != null) field.set(obj, value);
                } else if (type.equals("java.lang.Boolean")) {
                    Boolean value = map.get(key) == null ? null : Boolean.valueOf(map.get(key).toString());
                    if (value != null) field.set(obj, value);
                }
            }
            return obj;
        } catch (InstantiationException | IllegalAccessException e) {
            String errorMsg = "转换对象异常";
            logger.error(MessageFormattor.errorFormat(
                    this.getClass().getName(), "constructObject",
                    ExceptionType.EXCEPTION_DAO, errorMsg), e);
            throw new DaoException(ExceptionType.EXCEPTION_DAO, new ErrorVO(
                    ErrorDescription.ERR_CD_UT_DATE_CONVERSION,
                    ErrorDescription.ERR_CD_UT_DATE_CONVERSION, errorMsg));
        }
    }
其中,得到类变量的名字后,需要装驼峰形式转为下划线形式,调用了工具类:
 public static String toCamelUnderline(String str) {
        char[] chars = str.toCharArray();
        StringBuilder result = new StringBuilder();
        for (char c : chars) {
            //大写字母
            if (c <= 90 && c >= 65) {
                result.append("_").append((char)(c + 32));
            } else {
                result.append(c);
            }
        }
        if (result.length() > 0 && result.charAt(0) == '_') {
            result.deleteCharAt(0);
        }
        return result.toString();
    }

这里转换直接简单粗暴转为字符数组去处理,其实也可以用正则表达式去匹配然后递归调用,此法也可以。

最后,把调用函数 constructArticleKindResponse(map) 改为 constructObj(map, ArticleKindResponse.class)即可

测试,大功告成。


评论列表

    回复

    提示:您的邮箱只作博主联系您使用,不会显示在评论区. *为必填项