• JdbcTemplate实体映射


    JdbcTemplate实体映射

    如果你需要使用JdbcTemplate将查询的数据映射成Java POJO,那么这篇文章适合你。

    一个例子入门

    下面是一个将表中一行记录映射成Map的例子,也是JdbcTemplate默认提供的功能。

    List<Map<String, Object>> result = jdbcTemplate.queryForList("select id, name, age from tbl");
    

    然而,我们更希望得到的是下面这样的。

    List<User> result = jdbcTemplate.queryForList("select id, name, age from tbl", User.class);
    

    其中User中的属性与字段一一对应,还能自动将下划线转成驼峰。

    开始

    实现思路是通过反射将字段映射到对象对应的属性。

    核心代码

    public <T> List<T> queryForList(String sql, Class<T> clazz, Object... params) {
            final List<T> result = new ArrayList<>();
            jdbcTemplate.query(sql, params, rs -> {
                try {
                    // 字段名称
                    List<String> columnNames = new ArrayList<>();
                    ResultSetMetaData meta = rs.getMetaData();
                    int num = meta.getColumnCount();
                    for (int i = 0; i < num; i++) {
                        columnNames.add(meta.getColumnLabel(i + 1));
                    }
                    // 设置值
                    do {
                        T obj = clazz.getConstructor().newInstance();
                        for (int i = 0; i < num; i++) {
                            // 获取值
                            Object value = rs.getObject(i + 1);
                            // table.column形式的字段去掉前缀table.
                            String columnName = resolveColumn(columnNames.get(i));
                            // 下划线转驼峰
                            String property = CamelCaseUtils.toCamelCase(columnName);
                            // 复制值到属性,这是spring的工具类
                            BeanUtils.copyProperty(obj, property, value);
                        }
                        result.add(obj);
                    } while (rs.next());
                } catch (Exception e) {
                    throw new QueryException(e);
                }
            });
            if (CollectionUtils.isEmpty(result)) {
                return Collections.emptyList();
            }
            return result;
        }
    

    注意:

    • String columnName = resolveColumn(columnNames.get(i))用来去掉字段的表前缀,比如t.id替换成id
    • String property = CamelCaseUtils.toCamelCase(columnName)用来将字段的下划线转成属性的驼峰形式,比如page_view转换成pageView
    • BeanUtils.copyProperty(obj, property, value)是用来复制值到对象的属性中,BeanUtils是spring的工具类,经常会使用到

    下面是两个工具方法或类。

    去掉表前缀

    之所以去掉表前缀,是为了避免在SQL中使用别名,导致SQL过长。

    private String resolveColumn(String column) {
        final int notExistIndex = -1;
        int index = column.indexOf(".");
        if (index == notExistIndex) {
            return column;
        }
        return column.substring(index + 1);
    }
    

    字段下划线转成属性的驼峰

    当然,下划线转驼峰有很多更好的实现,这里不限制。如下是一个实现:

    public final class CamelCaseUtils {
    
        private static final char SEPARATOR = '_';
    
        private CamelCaseUtils() {
        }
    
        public static String toCamelCase(String input) {
            if (input == null) {
                return null;
            }
            input = input.toLowerCase();
            int length = input.length();
    
            StringBuilder sb = new StringBuilder(length);
            boolean upperCase = false;
            for (int i = 0; i < length; i++) {
                char c = input.charAt(i);
                if (c == SEPARATOR) {
                    upperCase = true;
                } else if (upperCase) {
                    sb.append(Character.toUpperCase(c));
                    upperCase = false;
                } else {
                    sb.append(c);
                }
            }
    
            return sb.toString();
        }
    
    }
    

    使用

    接下来就可以愉快的映射成POJO了:

    List<User> result = queryForList("select t.id, t.name, t.age, t.mobile_phone from tbl t where t.id < ?", User.class, 100L);
    

    如果参数比较多,还是通过数组传入:

    List<User> result = queryForList("select t.id, t.name, t.age, t.mobile_phone from tbl t where t.id < ?", User.class, new Object[]{100L});
    

    下面定义POJO:

    public class User implements Serializabl {
        
        private Long id;
    
        private String name;
    
        private Integer age;
    
        private String mobilePhone;
    
        // 省略到getters、setters
    }
    

    补充

    映射成一个值

    在count时,我们是希望返回一个值的,接下来是将结果映射成一个值。

    public <T> T queryOneColumn(String sql, Class<T> clazz, Object... params) {
        T result;
        if (ArrayUtils.isEmpty(params)) {
            result = jdbcTemplate.queryForObject(sql, clazz);
        } else {
            result = jdbcTemplate.queryForObject(sql, params, clazz);
        }
        return result;
    }
    

    使用:

    long total = queryOneColumn("select count(1) from tbl", Long.class);
    
  • 相关阅读:
    leetcode211
    leetcode209
    leetcode201
    leetcode1396
    leetcode1395
    leetcode1394
    leetcode1386
    leetcode1387
    leetcode1382
    leetcode1376
  • 原文地址:https://www.cnblogs.com/bener/p/10617065.html
Copyright © 2020-2023  润新知