如果你需要使用 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);
来源: http://www.bubuko.com/infodetail-3003219.html