您好,登錄后才能下訂單哦!
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);
}
免責(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)容。