利用Java針對MySql封裝的jdbc框架類 JdbcUtils 完整實現(xiàn)

最近看老羅的視頻,跟著完成了利用Java操作MySql數(shù)據(jù)庫的一個框架類JdbcUtils.java,完成對數(shù)據(jù)庫的增刪改查。其中查詢這塊,包括普通的查詢和利用反射完成的查詢,主要包括以下幾個函數(shù)接口:

1、public Connection getConnection() 獲得數(shù)據(jù)庫的連接

2、public boolean updateByPreparedStatement(String sql, Listparams)throws SQLException 更新數(shù)據(jù)庫,包括增加記錄、刪除記錄、改動某個記錄三個功能。

3、public Map findSimpleResult(String sql, List params) throws SQLException 查詢單條記錄,傳進去的是一個List參數(shù)填充占位符,返回的是一個Map.一個Map對應(yīng)一條完整的記錄,String對應(yīng)屬性名,Object是屬性值。

4、public List> findModeResult(String sql, List params) throws SQLException 查詢多條記錄,放在List里。

上面四個函數(shù)已經(jīng)包括了MySQl的所有操作,完全能夠滿足使用需要。視頻里老羅還擴展了兩個反射來查詢的函數(shù)。

5、public T findSimpleRefResult(String sql, List params,

Class cls )throws Exception 利用反射查詢單個記錄。

6、public List findMoreRefResult(String sql, List params,

Class cls )throws Exception 利用反射查詢多個記錄。

下面附完整代碼:

JdbcUtils.java

import java.lang.reflect.Field;  
import java.sql.Connection;  
import java.sql.DriverManager;  
import java.sql.PreparedStatement;  
import java.sql.ResultSet;  
import java.sql.ResultSetMetaData;  
import java.sql.SQLException;  
import java.util.ArrayList;  
import java.util.HashMap;  
import java.util.List;  
import java.util.Map;  
  
import domain.UserInfo;  
  
  
public class JdbcUtils {  
    //數(shù)據(jù)庫用戶名  
    private static final String USERNAME = "root";  
    //數(shù)據(jù)庫密碼  
    private static final String PASSWORD = "yanzi";  
    //驅(qū)動信息   
    private static final String DRIVER = "com.mysql.jdbc.Driver";  
    //數(shù)據(jù)庫地址  
    private static final String URL = "jdbc:mysql://localhost:3306/mydb";  
    private Connection connection;  
    private PreparedStatement pstmt;  
    private ResultSet resultSet;  
    public JdbcUtils() {  
        // TODO Auto-generated constructor stub  
        try{  
            Class.forName(DRIVER);  
            System.out.println("數(shù)據(jù)庫連接成功!");  
  
        }catch(Exception e){  
  
        }  
    }  
      
    /** 
     * 獲得數(shù)據(jù)庫的連接 
     * @return 
     */  
    public Connection getConnection(){  
        try {  
            connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);  
        } catch (SQLException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        return connection;  
    }  
  
      
    /** 
     * 增加、刪除、改 
     * @param sql 
     * @param params 
     * @return 
     * @throws SQLException 
     */  
    public boolean updateByPreparedStatement(String sql, List<Object>params)throws SQLException{  
        boolean flag = false;  
        int result = -1;  
        pstmt = connection.prepareStatement(sql);  
        int index = 1;  
        if(params != null && !params.isEmpty()){  
            for(int i=0; i<params.size(); i++){  
                pstmt.setObject(index++, params.get(i));  
            }  
        }  
        result = pstmt.executeUpdate();  
        flag = result > 0 ? true : false;  
        return flag;  
    }  
  
    /** 
     * 查詢單條記錄 
     * @param sql 
     * @param params 
     * @return 
     * @throws SQLException 
     */  
    public Map<String, Object> findSimpleResult(String sql, List<Object> params) throws SQLException{  
        Map<String, Object> map = new HashMap<String, Object>();  
        int index  = 1;  
        pstmt = connection.prepareStatement(sql);  
        if(params != null && !params.isEmpty()){  
            for(int i=0; i<params.size(); i++){  
                pstmt.setObject(index++, params.get(i));  
            }  
        }  
        resultSet = pstmt.executeQuery();//返回查詢結(jié)果  
        ResultSetMetaData metaData = resultSet.getMetaData();  
        int col_len = metaData.getColumnCount();  
        while(resultSet.next()){  
            for(int i=0; i<col_len; i++ ){  
                String cols_name = metaData.getColumnName(i+1);  
                Object cols_value = resultSet.getObject(cols_name);  
                if(cols_value == null){  
                    cols_value = "";  
                }  
                map.put(cols_name, cols_value);  
            }  
        }  
        return map;  
    }  
  
    /**查詢多條記錄 
     * @param sql 
     * @param params 
     * @return 
     * @throws SQLException 
     */  
    public List<Map<String, Object>> findModeResult(String sql, List<Object> params) throws SQLException{  
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();  
        int index = 1;  
        pstmt = connection.prepareStatement(sql);  
        if(params != null && !params.isEmpty()){  
            for(int i = 0; i<params.size(); i++){  
                pstmt.setObject(index++, params.get(i));  
            }  
        }  
        resultSet = pstmt.executeQuery();  
        ResultSetMetaData metaData = resultSet.getMetaData();  
        int cols_len = metaData.getColumnCount();  
        while(resultSet.next()){  
            Map<String, Object> map = new HashMap<String, Object>();  
            for(int i=0; i<cols_len; i++){  
                String cols_name = metaData.getColumnName(i+1);  
                Object cols_value = resultSet.getObject(cols_name);  
                if(cols_value == null){  
                    cols_value = "";  
                }  
                map.put(cols_name, cols_value);  
            }  
            list.add(map);  
        }  
  
        return list;  
    }  
  
    /**通過反射機制查詢單條記錄 
     * @param sql 
     * @param params 
     * @param cls 
     * @return 
     * @throws Exception 
     */  
    public <T> T findSimpleRefResult(String sql, List<Object> params,  
            Class<T> cls )throws Exception{  
        T resultObject = null;  
        int index = 1;  
        pstmt = connection.prepareStatement(sql);  
        if(params != null && !params.isEmpty()){  
            for(int i = 0; i<params.size(); i++){  
                pstmt.setObject(index++, params.get(i));  
            }  
        }  
        resultSet = pstmt.executeQuery();  
        ResultSetMetaData metaData  = resultSet.getMetaData();  
        int cols_len = metaData.getColumnCount();  
        while(resultSet.next()){  
            //通過反射機制創(chuàng)建一個實例  
            resultObject = cls.newInstance();  
            for(int i = 0; i<cols_len; i++){  
                String cols_name = metaData.getColumnName(i+1);  
                Object cols_value = resultSet.getObject(cols_name);  
                if(cols_value == null){  
                    cols_value = "";  
                }  
                Field field = cls.getDeclaredField(cols_name);  
                field.setAccessible(true); //打開javabean的訪問權(quán)限  
                field.set(resultObject, cols_value);  
            }  
        }  
        return resultObject;  
  
    }  
  
    /**通過反射機制查詢多條記錄 
     * @param sql  
     * @param params 
     * @param cls 
     * @return 
     * @throws Exception 
     */  
    public <T> List<T> findMoreRefResult(String sql, List<Object> params,  
            Class<T> cls )throws Exception {  
        List<T> list = new ArrayList<T>();  
        int index = 1;  
        pstmt = connection.prepareStatement(sql);  
        if(params != null && !params.isEmpty()){  
            for(int i = 0; i<params.size(); i++){  
                pstmt.setObject(index++, params.get(i));  
            }  
        }  
        resultSet = pstmt.executeQuery();  
        ResultSetMetaData metaData  = resultSet.getMetaData();  
        int cols_len = metaData.getColumnCount();  
        while(resultSet.next()){  
            //通過反射機制創(chuàng)建一個實例  
            T resultObject = cls.newInstance();  
            for(int i = 0; i<cols_len; i++){  
                String cols_name = metaData.getColumnName(i+1);  
                Object cols_value = resultSet.getObject(cols_name);  
                if(cols_value == null){  
                    cols_value = "";  
                }  
                Field field = cls.getDeclaredField(cols_name);  
                field.setAccessible(true); //打開javabean的訪問權(quán)限  
                field.set(resultObject, cols_value);  
            }  
            list.add(resultObject);  
        }  
        return list;  
    }  
  
    /** 
     * 釋放數(shù)據(jù)庫連接 
     */  
    public void releaseConn(){  
        if(resultSet != null){  
            try{  
                resultSet.close();  
            }catch(SQLException e){  
                e.printStackTrace();  
            }  
        }  
    }  
  
    /** 
     * @param args 
     */  
    public static void main(String[] args) throws SQLException {  
        // TODO Auto-generated method stub  
        JdbcUtils jdbcUtils = new JdbcUtils();  
        jdbcUtils.getConnection();  
  
        /*******************增*********************/  
        /*      String sql = "insert into userinfo (username, pswd) values (?, ?), (?, ?), (?, ?)"; 
        List<Object> params = new ArrayList<Object>(); 
        params.add("小明"); 
        params.add("123xiaoming"); 
        params.add("張三"); 
        params.add("zhangsan"); 
        params.add("李四"); 
        params.add("lisi000"); 
        try { 
            boolean flag = jdbcUtils.updateByPreparedStatement(sql, params); 
            System.out.println(flag); 
        } catch (SQLException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        }*/  
  
  
        /*******************刪*********************/  
        //刪除名字為張三的記錄  
        /*      String sql = "delete from userinfo where username = ?"; 
        List<Object> params = new ArrayList<Object>(); 
        params.add("小明"); 
        boolean flag = jdbcUtils.updateByPreparedStatement(sql, params);*/  
  
        /*******************改*********************/  
        //將名字為李四的密碼改了  
        /*      String sql = "update userinfo set pswd = ? where username = ? "; 
        List<Object> params = new ArrayList<Object>(); 
        params.add("lisi88888"); 
        params.add("李四"); 
        boolean flag = jdbcUtils.updateByPreparedStatement(sql, params); 
        System.out.println(flag);*/  
  
        /*******************查*********************/  
        //不利用反射查詢多個記錄  
        /*      String sql2 = "select * from userinfo "; 
        List<Map<String, Object>> list = jdbcUtils.findModeResult(sql2, null); 
        System.out.println(list);*/  
  
        //利用反射查詢 單條記錄  
        String sql = "select * from userinfo where username = ? ";  
        List<Object> params = new ArrayList<Object>();  
        params.add("李四");  
        UserInfo userInfo;  
        try {  
            userInfo = jdbcUtils.findSimpleRefResult(sql, params, UserInfo.class);  
            System.out.print(userInfo);  
        } catch (Exception e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
  
  
    }  
  
}  

根據(jù)上面代碼可以看到,數(shù)據(jù)庫名字:mydb,表名:userinfo,結(jié)構(gòu)如下:
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(64) | YES | | NULL | |
| pswd | varchar(64) | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
是用Nvicat提前創(chuàng)建好的:



因為有兩個接口用到了反射,因此對應(yīng)的JavaBean UserInfo.java代碼如下:

import java.io.Serializable;  
  
public class UserInfo implements Serializable{  
  
    /** 
     *  
     */  
    private static final long serialVersionUID = 1L;  
  
    private int id;  
    private String username;  
    private String pswd;  
      
    public UserInfo() {  
        // TODO Auto-generated constructor stub  
    }  
  
    public int getId() {  
        return id;  
    }  
  
    public void setId(int id) {  
        this.id = id;  
    }  
  
    public String getUsername() {  
        return username;  
    }  
  
    public void setUsername(String username) {  
        this.username = username;  
    }  
  
    public String getPswd() {  
        return pswd;  
    }  
  
    public void setPswd(String pswd) {  
        this.pswd = pswd;  
    }  
  
    @Override  
    public String toString() {  
        return "UserInfo [id=" + id + ", username=" + username + ", pswd="  
                + pswd + "]";  
    }  
}  

補充說明:

  1. 在安裝完mysql-connector-java-gpl-5.1.26.exe后會發(fā)現(xiàn)找不到j(luò)ar包,其實jar文件在C:\Program Files\MySQL\MySQL Connector J目錄下,有兩個jar包:

    用哪一個都o(jì)k。在Java工程里新建一個文件夾libs,然后將mysql-connector-java-5.1.26-bin.jar拷貝過去,右鍵單擊 add to build path就ok了。
    2.拋開這個框架類JdbcUtils.java來說,操作數(shù)據(jù)庫的一般性步驟如下:
    (1)連接數(shù)據(jù)庫,加載驅(qū)動: Class.forName(DRIVER); DRIVER = "com.mysql.jdbc.Driver";這本身就是反射?。?br> (2) 利用用戶名和密碼及數(shù)據(jù)庫的名字連接,這一步才是真正的連接:
    connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
    其中:String URL = "jdbc:mysql://localhost:3306/mydb";
    (3)編寫一個sql語句,其中的參數(shù)用?來代替,然后將參數(shù)寫到List里。
    執(zhí)行:pstmt = connection.prepareStatement(sql); 然后將參數(shù)從list里取出來填充到pstmt里。
    (4)如果是增、刪、改執(zhí)行:result = pstmt.executeUpdate(); 其中的result是執(zhí)行完影響的數(shù)據(jù)庫里的行數(shù),也即幾條記錄。如果是查詢執(zhí)行:resultSet = pstmt.executeQuery(); 返回的類型是ResultSet類型。之后就是把resultSet 弄成Map或List<Map>傳遞出去,給查詢者看。
    3.關(guān)于查詢操作,在得到resultSet后利用getMetaData得到表的結(jié)構(gòu)信息,如getColumnCount()得到有多少個列。String cols_name = metaData.getColumnName(i+1); 得到每個列的屬性名稱,如是id、username還是pswd.然后從Object cols_value = resultSet.getObject(cols_name);取出來,放到Map或List<Map>里。
    4.關(guān)于查詢里利用的反射操作,步驟如下:
    (1) T resultObject = cls.newInstance(); 利用class文件的newInstance()方法創(chuàng)建一個實例。
    (2)在通過getColumnCount()得到有多少個列之后,進入循環(huán),
    String cols_name = metaData.getColumnName(i+1); Object cols_value = resultSet.getObject(cols_name);
    讀取每一列的屬性名字和放的值。通過屬性的名字cols_name進行反射:Field field = cls.getDeclaredField(cols_name);這樣就得到了Field 等于類里的成員變量,field.setAccessible(true); //打開javabean的訪問權(quán)限 在利用set方法將從數(shù)據(jù)庫中查出來的cols_value通過JavaBean 也即定義的UserInfo這個類的 set方法賦進去。field.set(resultObject, cols_value);
    5.一般意義上,要利用Java的反射需要以下步驟
    (1)加載Class對象,這個一般有兩種方式:Class cls1 = UserInfo.class 或
    Class cls2 = Class.forName("domain.UserInfo") 后者是利用包名+類名的方法。
    (2)反射出來Class之后干啥事呢?一個類不外乎構(gòu)造函數(shù)、成員變量、成員函數(shù)。所以得到Class之后就可以干這三件事。
    A、關(guān)于構(gòu)造函數(shù),獲得Constructor 有四種方法:
    Constructor getConstructor(Class[] params)
    Constructor[] getConstructors()
    Constructor getDeclaredConstructor(Class[] params)
    Constructor[] getDeclaredConstructors()
    這四個函數(shù),如果不傳參數(shù)則是獲得所有的構(gòu)造函數(shù),得到的是一個集合。如果傳特定的參數(shù),則是尋找這個特定的構(gòu)造函數(shù),不帶Declared是獲得公共的public,帶了Declared是可以獲得私有構(gòu)造函數(shù)。 得到構(gòu)造函數(shù)后就可以利用反射創(chuàng)建實例了:
    Constructor con1[] = cls1.getDeclaredConstructors(); con1[1].setAccessible(true); Object obj1 = con1[1].newInstance(new Object[]{"tom"}); 如果直接調(diào)用clcs.newInstance()則是用默認的構(gòu)造函數(shù)創(chuàng)建實例。
    B、關(guān)于成員變量,同樣有四種方法:
    public Field getDeclaredField(String name) 獲取任意指定名字的成員 public Field[] getDeclaredFields() 獲取所有的成員變量 public Field getField(String name) 獲取任意public成員變量 public Field[] getFields() 獲取所有的public成員變量
    本文封裝的JdbcUtils類就是利用這種方式操作類里的私有成員變量,記得要setAccessible打開開關(guān)。如下:
    Field field = cls.getDeclaredField(cols_name); field.setAccessible(true); //打開javabean的訪問權(quán)限 field.set(resultObject, cols_value);
    C、關(guān)于成員函數(shù),也有四種方法:
    public Method[] getMethods() 獲取所有的共有方法的集合 public Method getMethod(String name,Class<?>... parameterTypes) 獲取指定公有方法 ,
    參數(shù)1:方法名 參數(shù)2:參數(shù)類型集合 public Method[] getDeclaredMethods() 獲取所有的方法 public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 獲取任意指定方法
    下面是利用文中的UserInfo這個類寫的一個完成的反射例子,拿到setUsername(String username)方法,然后反射。再拿到getUsername()方法再反射,然后打印出結(jié)果:
Class clcs = UserInfo.class;
        try {
            Object obj = clcs.newInstance();
            Method f = clcs.getDeclaredMethod("setUsername", String.class);
            f.invoke(obj, "yan123");
            Method f2 = clcs.getDeclaredMethod("getUsername", null);
            Object name = f2.invoke(obj, null);
            System.out.println("反射得到的名字 = "  +  name);


        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

在反射方法的時候,Method f = clcs.getDeclaredMethod("setUsername", String.class); 原函數(shù)里的輸入?yún)?shù)是什么類型,就寫什么類型.class. 如原來的setXXX需要輸入?yún)?shù)String,反射的時候就寫String.class.

  1. JavaBean是反射的一種,反射對構(gòu)造函數(shù)之類的沒任何要求,JavaBean要求這個類必須繼承Serializable即可串行化,另外構(gòu)造函數(shù)必須為public. 另外,就是JavaBean在得到某個field后可以直接調(diào)用set和get,而不必再反射得到method后再執(zhí)行。
    最后,反射是在程序運行的時候而非編譯時?。?!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容