JDBC--利用反射处理查询到的结果集

版权声明:本文为小斑马伟原创文章,转载请注明出处!
通用的查询方法:可以根据传入的 SQL、Class 对象返回 SQL 对应的记录的对象。
查询(要求:列的别名要和 Class 对应的类的属性名相同),得到 ResultSet 对象,得到 ResultSetMetaData 对象:可以知道 SQL 语句中查询了哪些列,以及列的别名都是什么,反射创建Class 对应的类对象,为对应的属性赋值。
实现查询到的数据列表信息与DAO对象绑定

主要步骤
1.先利用 SQL 进行查询,得到结果集
2.利用反射创建实体类的对象:创建 Student 对象
3.获取结果集的列的别名:idCard、studentName
4.再获取结果集的每一列的值, 结合 3 得到一个 Map,键:列的别名,值:列的值:{flowId:5, type:6, idCard: xxx ……}
5.再利用反射为 2 的对应的属性赋值:属性即为 Map 的键,值即为 Map 的值
/**
 * 通用的查询方法:可以根据传入的 SQL、Class 对象返回 SQL 对应的记录的对象
 * @param clazz: 描述对象的类型
 * @param sql: SQL 语句。可能带占位符
 * @param args: 填充占位符的可变参数。
 * @return
 */
public  T get(Class clazz, String sql, Object... args) {
    T entity = null;

    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet resultSet = null;

    try {
        //1. 得到 ResultSet 对象
        connection = JDBCTools.getConnection();
        preparedStatement = connection.prepareStatement(sql);
        for (int i = 0; i < args.length; i++) {
            preparedStatement.setObject(i + 1, args[i]);
        }
        resultSet = preparedStatement.executeQuery();

        //2. 得到 ResultSetMetaData 对象
        ResultSetMetaData rsmd = resultSet.getMetaData();
        
        //3. 创建一个 Map 对象, 键: SQL 查询的列的别名, 
        //值: 列的值
        Map values = new HashMap<>();
        
        //4. 处理结果集. 利用 ResultSetMetaData 填充 3 对应的 Map 对象
        if(resultSet.next()){
            for(int i = 0; i < rsmd.getColumnCount(); i++){
                String columnLabel = rsmd.getColumnLabel(i + 1);
                Object columnValue = resultSet.getObject(i + 1);
                
                values.put(columnLabel, columnValue);
            }
        }
        
        //5. 若 Map 不为空集, 利用反射创建 clazz 对应的对象
        if(values.size() > 0){
            entity = clazz.newInstance();
            
            //5. 遍历 Map 对象, 利用反射为 Class 对象的对应的属性赋值. 
            for(Map.Entry entry: values.entrySet()){
                String fieldName = entry.getKey();
                Object value = entry.getValue();
                ReflectionUtils.setFieldValue(entity, fieldName, value);
            }
        }
        

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        JDBCTools.releaseDB(resultSet, preparedStatement, connection);
    }

    return entity;
}
@Test
public void testGet() {
    String sql = "SELECT id, name, email, birth "
            + "FROM customers WHERE id = ?";


    Customer customer = get(Customer.class, sql, 5);
    System.out.println(customer);

    sql = "SELECT flow_id flowId, type, id_card idCard, "
            + "exam_card examCard, student_name studentName, "
            + "location, grade " + "FROM examstudent WHERE flow_id = ?";

    Student stu = get(Student.class, sql, 5);
    System.out.println(stu);
}

反射的 Utils 函数集合 提供访问私有变量, 获取泛型类型 Class, 提取集合中元素属性等 Utils 函数。

/**
 * 反射的 Utils 函数集合
 * 提供访问私有变量, 获取泛型类型 Class, 提取集合中元素属性等 Utils 函数
 * @author weiwei
 *
 */
 public class ReflectionUtils {


/**
 * 通过反射, 获得定义 Class 时声明的父类的泛型参数的类型
 * 如: public EmployeeDao extends BaseDao
 * @param clazz
 * @param index
 * @return
 */
@SuppressWarnings("unchecked")
public static Class getSuperClassGenricType(Class clazz, int index){
    Type genType = clazz.getGenericSuperclass();
    
    if(!(genType instanceof ParameterizedType)){
        return Object.class;
    }
    
    Type [] params = ((ParameterizedType)genType).getActualTypeArguments();
    
    if(index >= params.length || index < 0){
        return Object.class;
    }
    
    if(!(params[index] instanceof Class)){
        return Object.class;
    }
    
    return (Class) params[index];
}

/**
 * 通过反射, 获得 Class 定义中声明的父类的泛型参数类型
 * 如: public EmployeeDao extends BaseDao
 * @param 
 * @param clazz
 * @return
 */
@SuppressWarnings("unchecked")
public static Class getSuperGenericType(Class clazz){
    return getSuperClassGenricType(clazz, 0);
}

/**
 * 循环向上转型, 获取对象的 DeclaredMethod
 * @param object
 * @param methodName
 * @param parameterTypes
 * @return
 */
public static Method getDeclaredMethod(Object object, String methodName, Class[] parameterTypes){
    
    for(Class superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()){
        try {
            //superClass.getMethod(methodName, parameterTypes);
            return superClass.getDeclaredMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException e) {
            //Method 不在当前类定义, 继续向上转型
        }
        //..
    }
    
    return null;
}

/**
 * 使 filed 变为可访问
 * @param field
 */
public static void makeAccessible(Field field){
    if(!Modifier.isPublic(field.getModifiers())){
        field.setAccessible(true);
    }
}

/**
 * 循环向上转型, 获取对象的 DeclaredField
 * @param object
 * @param filedName
 * @return
 */
public static Field getDeclaredField(Object object, String filedName){
    
    for(Class superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()){
        try {
            return superClass.getDeclaredField(filedName);
        } catch (NoSuchFieldException e) {
            //Field 不在当前类定义, 继续向上转型
        }
    }
    return null;
}

/**
 * 直接调用对象方法, 而忽略修饰符(private, protected)
 * @param object
 * @param methodName
 * @param parameterTypes
 * @param parameters
 * @return
 * @throws InvocationTargetException 
 * @throws IllegalArgumentException 
 */
public static Object invokeMethod(Object object, String methodName, Class [] parameterTypes,
        Object [] parameters) throws InvocationTargetException{
    
    Method method = getDeclaredMethod(object, methodName, parameterTypes);
    
    if(method == null){
        throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]");
    }
    
    method.setAccessible(true);
    
    try {
        return method.invoke(object, parameters);
    } catch(IllegalAccessException e) {
        System.out.println("不可能抛出的异常");
    } 
    
    return null;
}

/**
 * 直接设置对象属性值, 忽略 private/protected 修饰符, 也不经过 setter
 * @param object
 * @param fieldName
 * @param value
 */
public static void setFieldValue(Object object, String fieldName, Object value){
    Field field = getDeclaredField(object, fieldName);
    
    if (field == null)
        throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
    
    makeAccessible(field);
    
    try {
        field.set(object, value);
    } catch (IllegalAccessException e) {
        System.out.println("不可能抛出的异常");
    }
}

/**
 * 直接读取对象的属性值, 忽略 private/protected 修饰符, 也不经过 getter
 * @param object
 * @param fieldName
 * @return
 */
public static Object getFieldValue(Object object, String fieldName){
    Field field = getDeclaredField(object, fieldName);
    
    if (field == null)
        throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
    
    makeAccessible(field);
    
    Object result = null;
    
    try {
        result = field.get(object);
    } catch (IllegalAccessException e) {
        System.out.println("不可能抛出的异常");
    }
    
    return result;
}
}

你可能感兴趣的:(JDBC--利用反射处理查询到的结果集)