jdbc 系列文章列表, 请查看目录: 《jdbc学习笔记》
Jdbc 比较繁琐的一个操作就是解析结果集ResultSet, 在实际开发时, 通常会将对结果集的解析封装为一个工具类. 需要注意的时, jdbc查询出来的属性可能不能直接转换为java的类型, 比如说java.sql.Date, 不能直接转换为java.util.Date 或LocalDate等类型, 需要自定义转换器. 如果比较熟悉Mybatis的话, 会发现Mybatis底层也封装了大量的类型转换器.
笔者的工具类比较简单, 只封装了三个方法:
方法签名方法描述参数说明public static LinkedHashMap<String, Object> 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: 结果集这是笔者对使用到的反射技术封装的一个简单工具类.
/** 反射工具类 * @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> T newInstance(Class<T> clz, HashMap<String, Object> propertiesMap, DateTypeConverter typeConverter){ // 如果属性为空, 则不进行创建, 返回null if (propertiesMap == null || propertiesMap.isEmpty()) { return null; } // 使用无参数构造方法创建对象 T t = null; try { t = clz.newInstance(); for (Map.Entry<String, Object> 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; } }笔者仅仅编写了一个日期类型的转换器, 在企业开发中, 可能需要用到的转换器会更多.
/** 日期类型转换器 * @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; } }测试时, 需要创建t_user表和javabean, 笔者这边仅给出javabean的定义.
public class UserPO { private Integer id; private String name; private String password; private LocalDate birthday; // 省略setter/getter/toString 方法 }