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