1. 程式人生 > >JDBC:利用反射封裝增刪改查操作

JDBC:利用反射封裝增刪改查操作

在學習了反射之後,知道了反射機制的強大,可以做很多事情。可以利用反射實現動態語言的部分特徵;可以利用反射獲取類的結構資訊,動態呼叫屬性和方法等等。因此,本文通過利用反射對JDBC的增刪改查的封裝加深對反射機制的瞭解。

1.反射的一些常用方法:

1.1、獲取Class的例項(三種):

        - Class c = 類名.class
      - Class c = Class.forName("類的全限定類名");
      - Class c = 物件.getClass();

1.2、獲取物件的類名

      - String className = c.getName();      //
獲取全限定類名
    - String className = c.getSimpleName();   //獲取簡單類名

1.3、獲取Field(四個方法):

       - Field field = c.getField("屬性名");     //該方法只能通過屬性名獲取public的屬性
    - Field[] field = c.getFields();       //獲取所有的public屬性陣列
    - Field field = c.getDeclaredField("屬性名"); //獲取類的屬性,包括protected/private

1.4、獲取Field的資訊

       - String
name = field.getName();  //獲取屬性名
    - Class<?> type = field.getType();  //獲取屬性的型別     - Object value = field.get(obj);    //獲取obj物件的field屬性的值     - field.set(obj,Object value);    //給obj物件的field屬性賦值value

1.5、設定可訪問性

        - setAccessible(true);  //可以用在被訪問修飾符修飾的地方,
                         //預設為false只能對public修飾的操作,設定true
可對private修飾的操作

2. 對增刪改查的封裝,只需要把一個物件當做引數轉入方法即可

2.1、插入

 /**
     * 類名對應表,屬性對應欄位
     * @param obj  傳入的物件
     * @return
     */
    public static boolean insert(Object obj) {
        boolean flag = false;
        Class<?> c = obj.getClass();        //獲取obj的Class

        //利用StringBuffer進行插入SQL語句的構造
        //通過反射獲取類名對映表名
        StringBuffer sb1 = new StringBuffer("insert into "+ c.getSimpleName() +"(");
        StringBuffer sb2 = new StringBuffer(" values(");

        Field[] field = c.getDeclaredFields();        //通過反射獲取物件的屬性陣列
        for(int i = 0; i < field.length; i++) {        //遍歷屬性構造SQL語句

            if(i != field.length-1) {
                sb1.append(field[i].getName()).append(",");
                sb2.append("?,");
            }else {
                sb1.append(field[i].getName()).append(")");
                sb2.append("?);");
            }
        }
        String sql = sb1.append(sb2).toString();
        //獲取資料庫連線,進行資料庫操作
        Connection conn = getConnection();
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(sql);
            for(int i = 0; i < field.length; i++) {    
                field[i].setAccessible(true);        //設定屬性的可訪問性,可以訪問私有屬性
                try {                                //通過Field的get(Object)方法獲取Object物件的屬性值
                    ps.setObject(i+1, field[i].get(obj));    //對預編譯的SQL語句中的?進行賦值
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(ps);        //返回執行的SQL語句
            flag = ps.execute();        //執行SQL
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {    
            close(ps);
            close(conn);    
        }
        return flag;
    }

 2.2、刪除
 

 /**
     * 通過主鍵(預設第一個屬性)刪除物件
     * @param obj
     * @return
     */
    public static boolean delete(Object obj) {
        boolean flag = false;
        Class<?> c = obj.getClass();        //獲取obj的Class
        //構造刪除的SQL語句
        StringBuffer sb = new StringBuffer("delete from ");
        sb.append(c.getSimpleName()).append(" where ");
        //獲取物件屬性陣列
        Field[] field = c.getDeclaredFields();
        //設定第一個屬性的可訪問性
        field[0].setAccessible(true);
        //獲取第一個屬性的屬性名構造刪除sql
        sb.append(field[0].getName()).append("=?");
        String sql = sb.toString();
        Connection conn = getConnection();
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(sql);
            ps.setObject(1, field[0].get(obj));    
            System.out.println(ps);
            flag = ps.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }finally {    
            close(ps);
            close(conn);    
        }
        return flag;
    }

 2.3、修改
 

/**
     * 模擬jdbc的更新操作,預設第一個屬性為主鍵
     * @param obj
     * @return
     */
    public static boolean update(Object obj) {
        boolean flag = false;
        Class<?> c = obj.getClass();
        StringBuffer sb = new StringBuffer("update "+ c.getSimpleName() +" set ");

        Field[] field = c.getDeclaredFields();
        for(int i = 1; i < field.length; i++) {            
            if(i != field.length-1) {
                sb.append(field[i].getName()).append("=?,");
            }else {
                sb.append(field[i].getName()).append("=? where ");
            }
        }
        sb.append(field[0].getName() + "=?");
        String sql = sb.toString();

        Connection conn = getConnection();
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(sql);
            for(int i = 1; i < field.length; i++) {
                field[i].setAccessible(true);
                ps.setObject(i, field[i].get(obj));
            }
            field[0].setAccessible(true);
            ps.setObject(field.length, field[0].get(obj));
            System.out.println(ps);
            flag = ps.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }finally {    
            close(ps);
            close(conn);    
        }
        return flag;
    }

 2.4、查詢,查詢操作不需要傳入一個物件,只需要一個類的Class就可以
 

/**
     * 模擬框架,通過物件的Class獲取對應表中的所有記錄
     * @param obj
     * @return
     */
    public static <T> List<T> selectAll(Class<T> c) {
        String sql = "select * from "+ c.getSimpleName();    //通過反射獲取類名對應表名構造SQL語句
        List<T> list = new ArrayList<T>();                    //儲存查詢結果
        Field[] field = c.getDeclaredFields();                //通過反射獲取所有屬性
        Connection conn = getConnection();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(sql);            
            System.out.println(ps);
            rs = ps.executeQuery();                    //返回結果集
            while(rs.next()) {
                T obj = c.newInstance();            //通過反射構造一個T型別的例項
                for(int i = 0; i < field.length; i++) {        //

                    field[i].setAccessible(true);            //設定屬性的可訪問性(可以訪問私有屬性)
                    field[i].set(obj, rs.getObject(field[i].getName()));    //通過屬性名獲取結果集中的值賦值到例項物件中
                }
                list.add(obj);            //將例項物件新增到list集合
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }finally {    
            close(rs);
            close(ps);
            close(conn);    
        }
        return list;
    }