溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

jdbc關(guān)于實現(xiàn)Mybatis結(jié)果集解析

發(fā)布時間:2020-06-19 19:48:43 來源:網(wǎng)絡(luò) 閱讀:330 作者:nineteens 欄目:編程語言

  Jdbc 比較繁瑣的一個操作就是解析結(jié)果集ResultSet, 在實際開發(fā)時, 通常會將對結(jié)果集的解析封裝為一個工具類. 需要注意的時, jdbc查詢出來的屬性可能不能直接轉(zhuǎn)換為java的類型, 比如說java.sql.Date, 不能直接轉(zhuǎn)換為java.util.Date 或LocalDate等類型, 需要自定義轉(zhuǎn)換器. 如果比較熟悉Mybatis的話, 會發(fā)現(xiàn)Mybatis底層也封裝了大量的類型轉(zhuǎn)換器.

  1. 工具類源碼

  筆者的工具類比較簡單, 只封裝了三個方法:

  方法簽名  方法描述  參數(shù)說明

  public static LinkedHashMap toPropertyMap(ResultSet resultSet) throws SQLException  轉(zhuǎn)換單行結(jié)果集為Map結(jié)構(gòu). key為列別名, value為列值  resultSet: 查詢結(jié)果集

  public static T toBean(ResultSet resultSet, Class clz)  轉(zhuǎn)換結(jié)果集為單行對象  clz: 目標(biāo)對象類型

  resultSet: 結(jié)果集

  public static List toBeans(ResultSet resultSet, Class clz) throws SQLException  轉(zhuǎn)換結(jié)果集為java對象集合.  clz: 要轉(zhuǎn)換的javaBean類

  resultSet: 結(jié)果集

  1.1 ResultSetUtil 源碼

  /** 結(jié)果集解析工具類

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

  public class ResultSetUtil {

  /** 轉(zhuǎn)換單行結(jié)果集為Map結(jié)構(gòu). key為列別名, value為列值

  * @param resultSet 查詢結(jié)果集

  * @return 結(jié)果集中為空時, 返回null

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

  public static LinkedHashMap toPropertyMap(ResultSet resultSet) throws SQLException {

  // 如果結(jié)果集為空,則返回null

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

  LinkedHashMap cloumnMap = new LinkedHashMap<>();

  // 獲取結(jié)果集元信息

  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;

  }

  /** 轉(zhuǎn)換結(jié)果集為單行對象

  * @param clz 目標(biāo)對象類型

  * @param resultSet 結(jié)果集

  * @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 執(zhí)行異常!", e);

  }

  }

  /** 轉(zhuǎn)換結(jié)果集為java對象集合.

  * @param clz 要轉(zhuǎn)換的javaBean類

  * @param resultSet 結(jié)果集

  * @return 結(jié)果集中沒有數(shù)據(jù)時, 返回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;

  // 解析結(jié)果集

  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 源碼

  這是筆者對使用到的反射技術(shù)封裝的一個簡單工具類.

  /** 反射工具類

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

  public class ReflectUtil {

  /**為對象屬性賦值

  * @param target 目標(biāo)對象

  * @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 目標(biāo)對象

  * @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);

  }

  }

  /** 反射創(chuàng)建對象

  * @param clz 目標(biāo)對象的類型

  * @return propertiesMap 目標(biāo)對象的屬性與值

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

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

  // 如果屬性為空, 則不進(jìn)行創(chuàng)建, 返回null

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

  return null;

  }

  // 使用無參數(shù)構(gòu)造方法創(chuàng)建對象

  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();

  // 使用類型轉(zhuǎn)換器轉(zhuǎn)換參數(shù)類型

  value = typeConverter.convert(value, propertyType);

  // 調(diào)用set方法, 賦值

  Method writeMethod = propertyDescriptor.getWriteMethod();

  writeMethod.invoke(t, value);

  }

  } catch (Exception e) {

  throw new RuntimeException("反射創(chuàng)建對象失敗!", e);

  }

  return t;

  }

  } 無錫看婦科的醫(yī)院 http://www.ytsgfk120.com/

  1.3 DateTypeConverter 轉(zhuǎn)換器

  筆者僅僅編寫了一個日期類型的轉(zhuǎn)換器, 在企業(yè)開發(fā)中, 可能需要用到的轉(zhuǎn)換器會更多.

  /** 日期類型轉(zhuǎn)換器

  * @since 1.0

  * @author zongf

  * @created 2019-07-18

  */

  public class DateTypeConverter {

  /** 轉(zhuǎn)換對象的類型

  * @param value 值

  * @param javaType java類型

  * @return 轉(zhuǎn)換后的類型

  * @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 創(chuàng)建javaBean

  測試時, 需要創(chuàng)建t_user表和javabean, 筆者這邊僅給出javabean的定義.

  public class UserPO {

  private Integer id;

  private String name;

  private String password;

  private LocalDate birthday;

  // 省略setter/getter/toString 方法

  }

  2.2 測試用例

  // 測試轉(zhuǎn)換單個對象為Map 結(jié)構(gòu)

  @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));

  }

  // 測試轉(zhuǎn)換對象為單個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);

  }

  // 測試轉(zhuǎn)換對象為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問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI