zoukankan      html  css  js  c++  java
  • <五>JDBC_利用反射及JDBC元数据编写通用的查询方法

    此类针对javaBean类写了一个通用的查询方法,List<javaBean> 通用查询更新中...;通过学习,深刻体会到学会反射就等于掌握了java基础的半壁江山!

    一、使用JDBC驱动程序处理元数据:
     *   .java通过JDBC获得连接后得到一个Connection对象,可以从这个对象获得有关数据库管理系统的各种信息,
     *   包括数据库的各个表,表中的各个列,数据类型,触发器,存储过程等各方面的信息。根据这些信息,JDBC可以访问
     *   一个事先并不了解的数据库。
     *   .获取这些信息的方法都是在DataBaseMetaData类的对象上实现的,而DataBaseMetaData对象是在
     *   Connection对象上获得的。
    二、ResultSetMetaData类
     *   .是描述ResultSet的元数据对象,可用于获取ResultSet对象中列的类型和属性信息的对象:
     *    ---getColumnName(int column) :获取指定列的名称
     *    ---getColumnCount() : 返回当前ResultSet对象中的列数
     *    ---getColumnLabel(int column) : 获取指定列的别名(索引从1开始)
     *    ---getColumnTypeName() : 检索指定列的数据库特定的类型名称
     *    ---getColumnDisplaySize() : 指示指定列的最大标准宽度,以字符为单位
     *    ---isNullable(int column) : 指示指定列中的值是否可以为null
     *    ---isAutoIncrement() : 指示是否自动为指定列进行编号,这样这些列仍然是只读的。
     *    
     *    调用ResultSet的getMetaData()方法得到ResultSetMetaData对象。

    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.ResultSetMetaData;
    import java.util.HashMap;
    import java.util.Map;

    import org.junit.Test;

    public class JDBCTest2 {
     
     @Test
     public void testGet(){
        String sql="select id,name,email,birth from customers where id=?";
      
        Customer customer=get(Customer.class,sql,2);
        System.out.println(customer);
        /*
         * **FlowID对应数据库表属性字段,要求别名(flow_Id)对应javaBean的属性名**
         *   解析sql语句中列的别名、值,再通过反射技术把值赋给对应的属性,详细过程如下:
         *     1、先利用SQL语句进行查询,得到结果集
         *     2、利用反射创建实体类的对象
         *     3、获取结果集列的别名
         *      如何获取?
         *     4、再获取结果集的每一列的值,结合3得到一个Map,键:列的别名,值:列的值
         *     5、再利用反射为2的对应的属性赋值,属性即为Map的键,值即为Map的值。
         * */
        sql="select FlowId flow_Id,Type,IDCard,ExamCard,StudentName from examstudent where FlowId=?";
        Student stu=get(Student.class,sql,1);
        System.out.println(stu);
      
       }
        public <T> T get(Class<T> clazz, String sql,Object... args){
      
          /* 0、得到ResultSet对象
           * 1、得到ResultSetMetaData的对象
           * 2、创建一个Map<String,Object>对象
           * 3、处理结果集,利用ResultSetMetaData填充2对应的Map对象
           * 4、若Map不为空集,利用反射创建clazz对应的对象
           * 5、遍历Map对象,利用反射为Class对象对应的属性赋值
           *
           * */
      
          T entity=null;
      
          Connection con=null;
          PreparedStatement ps=null;
          ResultSet rs=null;
      
          try {
       
             con=JDBCTools.getConnection();
             ps=con.prepareStatement(sql);
             for (int i = 0; i < args.length; i++) {
                ps.setObject(i+1, args[i]);
             }
             rs=ps.executeQuery();
       
             ResultSetMetaData rsmd=rs.getMetaData();
       
             Map<String,Object> values=new HashMap<>();
             //因获取的是一个类...,所以if非while
             if(rs.next()) {
                for (int i = 0; i < rsmd.getColumnCount(); i++) {
                   String columnLabel=rsmd.getColumnLabel(i+1);
                   Object columnValue=rs.getObject(i+1);
                   values.put(columnLabel, columnValue);
                }
        
             }
             //若Map不为空
             if (values.size()>0) {
                entity=clazz.newInstance();
                //为javaBean的属性赋值
                for (Map.Entry<String, Object> entry:values.entrySet()) {
                     String fieldName=entry.getKey();
                     Object value=entry.getValue();
                      ReflectionUtils.setFieldValue(entity, fieldName, value);
                }
             }
       
       
          } catch (Exception e) {
             e.printStackTrace();
          }finally{
             JDBCTools.release(rs, ps, con);
          }
      
          return entity;
       }
     }

     帮助工具类

    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;

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

     
     /**
      * 通过反射, 获得定义 Class 时声明的父类的泛型参数的类型
      * 如: public EmployeeDao extends BaseDao<Employee, String>
      * @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<Employee, String>
      * @param <T>
      * @param clazz
      * @return
      */
     @SuppressWarnings("unchecked")
     public static<T> Class<T> 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;
     }
    }

    总结:

    1、why:如果只有一个结果集。但不知道结果集中有多少列,列的名字都是什么?

    1>编写通用的查询方法时需要使用;

    public <T> T get(Class<T> clazz,String sql,Object...sql)

    2、what:用于描述ResultSet的对象。

    3、how

    1>得到ResultSetMetaData对象:调用ResultSet的getMetaData()方法

      ResultSetMetaData rsmd=resultSet.getMetaData();

    2>ResultSetMetaData有哪些好用的方法:

      >int getColumnCount()结果集中包含哪些列

      >String getColumnLabel(int column):获取指定列的别名,其中索引从1开始。

  • 相关阅读:
    Django Restframework 实践(二)
    mysql in 过滤 解决转义问题
    automapper
    autoface
    各种文件上传 转载
    REST Client
    MySql PartionBy
    mysql 变量名称不能与表字段一致
    mysql 存储过程分页 转载
    dapper.net 转载
  • 原文地址:https://www.cnblogs.com/iamkk/p/6060095.html
Copyright © 2011-2022 走看看