JAVA jdbc封装 DbUtilsBean-查询方法支持指定封装类(反射)

说明

类似 Mybatis,支持将查询结果封装到 Bean中

缺点

使用 反射 实现,繁琐麻烦,使用 内省 方式,更加简单,详见 链接

继承

需要继承 某个 DbUtils 类 或 子类即可

代码

/**
 * 指定封装类,将查询的结果封装到该类中
 * 注意:列名要与类成员变量名相同,才能封装
 *
 * @param sql
 * @param clazz 指定封装类
 * @return
 * @throws SQLException
 * @throws InstantiationException
 * @throws IllegalAccessException
 * @throws IllegalArgumentException
 * @throws InvocationTargetException
 */
public <T> List<T> queryBean(String sql,Class<T> clazz,Object ... objects) throws SQLException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException {
    List retList = new ArrayList<>();
    Map<String, Method> propertyAndSetterMap = getSetterMethod(clazz);
    PreparedStatement pstm = null;
    ResultSet rs = null;
    try {
        pstm = conn.prepareStatement(sql);
        if (objects != null && objects.length > 0) {
            for (int i = 0; i < objects.length; i++) {
                pstm.setObject(i + 1, objects[i]);
            }
        }
        rs = pstm.executeQuery();
        ResultSetMetaData rsmd = rs.getMetaData();
        // 返回查询结果列的总数
        int columnNum = rsmd.getColumnCount();
        while (rs.next()) {
            // 通过反射方式实例化
            Object beanObj = clazz.newInstance();
            // 将查询列的值,放入到 javabean(模型类)的 属性中
            // ****难点:需要知道列名,还需要指定属性名
            // 即:原来写的下面这行代码
//            user.setUserId(resultSet.getInt("user_id"));
            for (int i = 1; i <= columnNum; i++) {
                // 取出查询的列名,都改成小写,成员变量名那里也改成小写了
                String columnLabel = rsmd.getColumnLabel(i).toLowerCase();
                // 取出与该列名相应的值
                Object valueDB = rs.getObject(i);
                // 根据列名,从map中取出与列名相同的属性的set方法
                Method setMethod = propertyAndSetterMap.get(columnLabel);
                // 如果方法为null,表示没有对应的方法,就不再往下执行
                if (setMethod == null) {
                    continue;
                }
                // set方法一定有一个参数
                Class paraType = setMethod.getParameterTypes()[0];
                Object dataTemp = null;
                if (valueDB instanceof BigDecimal) { // mysql数据库的 decimal 类型,jdbc查询出来的类型是 BigDecimal,需要做额外处理
                    BigDecimal temp = (BigDecimal) valueDB;
                    if (paraType == double.class) {
                        dataTemp = temp.doubleValue();
                    } else if (paraType == float.class) {
                        dataTemp = temp.floatValue();
                    }
                } else {
                    dataTemp = valueDB;
                }
                // 调用 set 方法,传值
                setMethod.invoke(beanObj,dataTemp);
                // 动态调用 setXXX 方法,并且传值
                try {
                    setMethod.invoke(beanObj,dataTemp);
                }catch (java.lang.IllegalArgumentException e){
                    throw new IllegalArgumentException(setMethod.getName()+" 形参类型是:"+setMethod.getParameterTypes()[0]+
                            ",从数据库查询出来的数据类型是:"+dataTemp.getClass().getName());
                }
            }
            retList.add(beanObj);
        }
        return retList;
    }finally{
        //查询后要释放资源
        if(rs!=null) {
            rs.close();
        }
        if(pstm!=null) {
            pstm.close();
        }
    }

}

/**
 * 获取setter方法
 * @param bean
 * @return 返回Map,属性名作为key,setter方法作为value
 */
private Map<String,Method> getSetterMethod(Class bean) throws IntrospectionException {

    // 将属性 和 相关的set方法,放入到map中
    Map<String,Method> propertyAndSetterMap = new HashMap();
    Method[] methods = bean.getMethods();
    for (Method method : methods) {
        String methodName = method.getName();
        // 如果方法以set开头,就认为是set方法
        if (methodName.startsWith("set")) {
            // 如果方法的参数数量不是1,就说明不是set方法
            if(method.getParameterCount()!=1){
                continue;
            }
            // 截取set后面的部分,作为成员变量名,也是列名
            String field = methodName.substring(3).toLowerCase();
            propertyAndSetterMap.put(field,method);
        }
    }


    return propertyAndSetterMap;
}

原文出处:/show_1IX2ymkvpzD5.html