温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

jdbc关于实现Mybatis结果集解析

发布时间:2020-06-19 19:48:43 来源:网络 阅读:330 作者:nineteens 栏目:编程语言

  Jdbc 比较繁琐的一个操作就是解析结果集ResultSet, 在实际开发时, 通常会将对结果集的解析封装为一个工具类. 需要注意的时, jdbc查询出来的属性可能不能直接转换为java的类型, 比如说java.sql.Date, 不能直接转换为java.util.Date 或LocalDate等类型, 需要自定义转换器. 如果比较熟悉Mybatis的话, 会发现Mybatis底层也封装了大量的类型转换器.

  1. 工具类源码

  笔者的工具类比较简单, 只封装了三个方法:

  方法签名  方法描述  参数说明

  public static LinkedHashMap toPropertyMap(ResultSet resultSet) throws SQLException  转换单行结果集为Map结构. key为列别名, value为列值  resultSet: 查询结果集

  public static T toBean(ResultSet resultSet, Class clz)  转换结果集为单行对象  clz: 目标对象类型

  resultSet: 结果集

  public static List toBeans(ResultSet resultSet, Class clz) throws SQLException  转换结果集为java对象集合.  clz: 要转换的javaBean类

  resultSet: 结果集

  1.1 ResultSetUtil 源码

  /** 结果集解析工具类

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

  public class ResultSetUtil {

  /** 转换单行结果集为Map结构. key为列别名, value为列值

  * @param resultSet 查询结果集

  * @return 结果集中为空时, 返回null

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

  public static LinkedHashMap toPropertyMap(ResultSet resultSet) throws SQLException {

  // 如果结果集为空,则返回null

  if (!resultSet.next()) return null;

  LinkedHashMap cloumnMap = new LinkedHashMap<>();

  // 获取结果集元信息

  ResultSetMetaData metaData = resultSet.getMetaData();

  // 获取每一列列名与值

  for (int i = 1; i <= metaData.getColumnCount(); i++) {

  // 获取列别名为key

  String columnLabel = metaData.getColumnLabel(i);

  Object columnValue = resultSet.getObject(i);

  cloumnMap.put(columnLabel, columnValue);

  }

  return cloumnMap;

  }

  /** 转换结果集为单行对象

  * @param clz 目标对象类型

  * @param resultSet 结果集

  * @since 1.0

  * @return null

  * @author zongf

  * @created 2019-07-18

  */

  public static T toBean(ResultSet resultSet, Class clz) {

  try {

  LinkedHashMap propertyMap = toPropertyMap(resultSet);

  return ReflectUtil.newInstance(clz, propertyMap, new DateTypeConverter());

  } catch (SQLException e) {

  throw new RuntimeException("sql 执行异常!", e);

  }

  }

  /** 转换结果集为java对象集合.

  * @param clz 要转换的javaBean类

  * @param resultSet 结果集

  * @return 结果集中没有数据时, 返回null

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

  public static List toBeans(ResultSet resultSet, Class clz) throws SQLException {

  List list = new ArrayList<>();

  LinkedHashMap propertyMap = null;

  // 解析结果集

  while ((propertyMap = toPropertyMap(resultSet)) != null) {

  T t = (T) ReflectUtil.newInstance(clz, propertyMap, new DateTypeConverter());

  if(t != null) list.add(t);

  }

  return list.size() > 0 ? list : null;

  }

  }

  1.2 ReflectUtil 源码

  这是笔者对使用到的反射技术封装的一个简单工具类.

  /** 反射工具类

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

  public class ReflectUtil {

  /**为对象属性赋值

  * @param target 目标对象

  * @param property 属性名

  * @param property 属性名

  * @return value 属性值

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

  public static void setPropertyValue(Object target, String property, Object value) {

  try {

  PropertyDescriptor descriptor = new PropertyDescriptor(property, target.getClass());

  Method writeMethod = descriptor.getWriteMethod();

  writeMethod.invoke(target, value);

  } catch (Exception e) {

  throw new RuntimeException("为对象属性赋值异常!",e);

  }

  }

  /** 获取对象属性值

  * @param target 目标对象

  * @param property 属性

  * @return Object 返回对象属性值

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

  public static Object getPropertyValue(Object target, String property) {

  try {

  PropertyDescriptor descriptor = new PropertyDescriptor(property, target.getClass());

  Method readMethod = descriptor.getReadMethod();

  return readMethod.invoke(target);

  } catch (Exception e) {

  throw new RuntimeException("获取对象属性异常!",e);

  }

  }

  /** 反射创建对象

  * @param clz 目标对象的类型

  * @return propertiesMap 目标对象的属性与值

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

  public static T newInstance(Class clz, HashMap propertiesMap, DateTypeConverter typeConverter){

  // 如果属性为空, 则不进行创建, 返回null

  if (propertiesMap == null || propertiesMap.isEmpty()) {

  return null;

  }

  // 使用无参数构造方法创建对象

  T t = null;

  try {

  t = clz.newInstance();

  for (Map.Entry entry : propertiesMap.entrySet()) {

  // 获取对象属性与值

  String property = entry.getKey();

  Object value = entry.getValue();

  // 获取属性描述符

  PropertyDescriptor propertyDescriptor = new PropertyDescriptor(property, clz);

  // 获取属性类型

  Class propertyType = propertyDescriptor.getPropertyType();

  // 使用类型转换器转换参数类型

  value = typeConverter.convert(value, propertyType);

  // 调用set方法, 赋值

  Method writeMethod = propertyDescriptor.getWriteMethod();

  writeMethod.invoke(t, value);

  }

  } catch (Exception e) {

  throw new RuntimeException("反射创建对象失败!", e);

  }

  return t;

  }

  } 无锡看妇科的医院 http://www.ytsgfk120.com/

  1.3 DateTypeConverter 转换器

  笔者仅仅编写了一个日期类型的转换器, 在企业开发中, 可能需要用到的转换器会更多.

  /** 日期类型转换器

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

  public class DateTypeConverter {

  /** 转换对象的类型

  * @param value 值

  * @param javaType java类型

  * @return 转换后的类型

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

  public Object convert(Object value, Class javaType) {

  Object obj = value;

  // 如果是java 日期

  if(javaType.equals(Date.class)) {

  java.sql.Date date = (java.sql.Date) value;

  obj = date.toInstant().getEpochSecond();

  // 如果是java8 日期

  } else if(javaType.equals(LocalDate.class)){

  obj = ((java.sql.Date) value).toLocalDate();

  } else {

  obj = value;

  }

  return obj;

  }

  }

  2. 单元测试

  2.1 创建javaBean

  测试时, 需要创建t_user表和javabean, 笔者这边仅给出javabean的定义.

  public class UserPO {

  private Integer id;

  private String name;

  private String password;

  private LocalDate birthday;

  // 省略setter/getter/toString 方法

  }

  2.2 测试用例

  // 测试转换单个对象为Map 结构

  @Test

  public void toPropertyMap() throws SQLException {

  String str = "select id uId, name , pwd, birthday from t_user where id = 1001";

  Connection connection = DbConnUtil.getConnection(true);

  Statement statement = connection.createStatement();

  ResultSet resultSet = statement.executeQuery(str);

  LinkedHashMap map = ResultSetUtil.toPropertyMap(resultSet);

  map.forEach((key, val) -> System.out.println(key + ":" + val));

  }

  // 测试转换对象为单个bean

  @Test

  public void toBean() throws SQLException {

  String str = "select * from t_user where id = 1002";

  Connection connection = DbConnUtil.getConnection(true);

  Statement statement = connection.createStatement();

  ResultSet resultSet = statement.executeQuery(str);

  UserPO userPO = ResultSetUtil.toBean(resultSet, UserPO.class);

  System.out.println(userPO);

  }

  // 测试转换对象为bean列表

  @Test

  public void toBeans() throws SQLException {

  String str = "select * from t_user ";

  Connection connection = DbConnUtil.getConnection(true);

  Statement statement = connection.createStatement();

  ResultSet resultSet = statement.executeQuery(str);

  List userPOList = ResultSetUtil.toBeans(resultSet, UserPO.class);

  userPOList.forEach(System.out::println);

  }


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI