jdbc关于实现Mybatis结果集解析

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

浦江网站制作公司哪家好,找成都创新互联!从网页设计、网站建设、微信开发、APP开发、成都响应式网站建设公司等网站项目制作,到程序开发,运营维护。成都创新互联于2013年开始到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选成都创新互联

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

}


本文标题:jdbc关于实现Mybatis结果集解析
文章网址:http://hbruida.cn/article/gjjeeh.html