?
最近看老羅的視頻,跟著完成了利用Java操作MySQL數據庫的一個框架類JdbcUtils.java,完成對數據庫的增刪改查。其中查詢這塊,包括普通的查詢和利用反射完成的查詢,主要包括以下幾個函數接口:
1、public Connection getConnection() ? 獲得數據庫的連接
2、public boolean updateByPreparedStatement(String sql, List<Object>params)throws SQLException ?更新數據庫,包括增加記錄、刪除記錄、改動某個記錄三個功能。
3、public Map<String, Object> findSimpleResult(String sql, List<Object> params) throws SQLException 查詢單條記錄,傳進去的是一個List<Object>參數填充占位符,返回的是一個Map<String, Object>.一個Map對應一條完整的記錄,String對應屬性名,Object是屬性值。
4、public List<Map<String, Object>> findModeResult(String sql, List<Object> params) throws SQLException 查詢多條記錄,放在List里。
上面四個函數已經包括了MySQl的所有操作,完全能夠滿足使用需要。視頻里老羅還擴展了兩個反射來查詢的函數。
5、public <T> T findSimpleRefResult(String sql, List<Object> params,
Class<T> cls )throws Exception ? 利用反射查詢單個記錄。
6、 public <T> List<T> findMoreRefResult(String sql, List<Object> params,
Class<T> cls )throws Exception ? 利用反射查詢多個記錄。
下面附完整代碼:
JdbcUtils.java
?
[java]?view plaincopy print?
<span?style="font-size:18px;">package?com.jdbc.dbutils;????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?{??????????private?static?final?String?USERNAME?=?"root";??????????private?static?final?String?PASSWORD?=?"yanzi";??????????private?static?final?String?DRIVER?=?"com.mysql.jdbc.Driver";??????????private?static?final?String?URL?=?"jdbc:mysql://localhost:3306/mydb";??????private?Connection?connection;??????private?PreparedStatement?pstmt;??????private?ResultSet?resultSet;??????public?JdbcUtils()?{??????????????????try{??????????????Class.forName(DRIVER);??????????????System.out.println("數據庫連接成功!");????????????}catch(Exception?e){????????????}??????}????????????????public?Connection?getConnection(){??????????try?{??????????????connection?=?DriverManager.getConnection(URL,?USERNAME,?PASSWORD);??????????}?catch?(SQLException?e)?{??????????????????????????e.printStackTrace();??????????}??????????return?connection;??????}??????????????????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;??????}????????????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();????????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;??????}????????????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;??????}????????????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()){??????????????????????????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);?????????????????field.set(resultObject,?cols_value);??????????????}??????????}??????????return?resultObject;????????}????????????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()){??????????????????????????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);?????????????????field.set(resultObject,?cols_value);??????????????}??????????????list.add(resultObject);??????????}??????????return?list;??????}????????????public?void?releaseConn(){??????????if(resultSet?!=?null){??????????????try{??????????????????resultSet.close();??????????????}catch(SQLException?e){??????????????????e.printStackTrace();??????????????}??????????}??????}????????????public?static?void?main(String[]?args)?throws?SQLException?{??????????????????JdbcUtils?jdbcUtils?=?new?JdbcUtils();??????????jdbcUtils.getConnection();??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????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)?{??????????????????????????e.printStackTrace();??????????}??????????}????}??</span>??
根據上面代碼可以看到,數據庫名字:mydb,表名:userinfo,結構如下:
?
+----------+-------------+------+-----+---------+----------------+
| 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提前創建好的:
因為有兩個接口用到了反射,因此對應的JavaBean?UserInfo.java代碼如下:
?
[java]?view plaincopy print?
<span?style="font-size:18px;">package?domain;????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()?{??????????????}????????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?+?"]";??????}????????????}??</span>??
補充說明:
?
1. 在安裝完mysql-connector-java-gpl-5.1.26.exe后會發現找不到jar包,其實jar文件在C:\Program Files\MySQL\MySQL Connector J目錄下,有兩個jar包:
用哪一個都ok。在Java工程里新建一個文件夾libs,然后將mysql-connector-java-5.1.26-bin.jar拷貝過去,右鍵單擊 add to build path就ok了。
2.拋開這個框架類JdbcUtils.java來說,操作數據庫的一般性步驟如下:
? ? (1)連接數據庫,加載驅動:?Class.forName(DRIVER);?DRIVER = "com.mysql.jdbc.Driver";這本身就是反射!!
? ? ? (2) 利用用戶名和密碼及數據庫的名字連接,這一步才是真正的連接:
connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);?
其中:String URL = "jdbc:mysql://localhost:3306/mydb";
? ? ?(3)編寫一個sql語句,其中的參數用?來代替,然后將參數寫到List里。
執行:pstmt = connection.prepareStatement(sql); 然后將參數從list里取出來填充到pstmt里。
? ? ?(4)如果是增、刪、改執行:result = pstmt.executeUpdate(); 其中的result是執行完影響的數據庫里的行數,也即幾條記錄。如果是查詢執行:resultSet = pstmt.executeQuery(); 返回的類型是ResultSet類型。之后就是把resultSet 弄成Map或List<Map>傳遞出去,給查詢者看。
3.關于查詢操作,在得到resultSet后利用getMetaData得到表的結構信息,如getColumnCount()得到有多少個列。String cols_name = metaData.getColumnName(i+1); 得到每個列的屬性名稱,如是id、username還是pswd.然后從Object cols_value = resultSet.getObject(cols_name);取出來,放到Map或List<Map>里。
4.關于查詢里利用的反射操作,步驟如下:
? ? ?(1)?T resultObject = cls.newInstance(); 利用class文件的newInstance()方法創建一個實例。
? ? ?(2)在通過getColumnCount()得到有多少個列之后,進入循環,
? ? ? ? ? ? ? ? ?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的訪問權限 在利用set方法將從數據庫中查出來的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之后干啥事呢?一個類不外乎構造函數、成員變量、成員函數。所以得到Class之后就可以干這三件事。
? ? ?A、關于構造函數,獲得Constructor 有四種方法:?
? Constructor getConstructor(Class[] params)?
Constructor[] getConstructors()?
Constructor getDeclaredConstructor(Class[] params)?
? Constructor[] getDeclaredConstructors()??
這四個函數,如果不傳參數則是獲得所有的構造函數,得到的是一個集合。如果傳特定的參數,則是尋找這個特定的構造函數,不帶Declared是獲得公共的public,帶了Declared是可以獲得私有構造函數。 得到構造函數后就可以利用反射創建實例了:
?Constructor con1[] = cls1.getDeclaredConstructors();
? ? ? ? ?con1[1].setAccessible(true);
? ? ?Object obj1 = con1[1].newInstance(new Object[]{"tom"}); 如果直接調用clcs.newInstance()則是用默認的構造函數創建實例。
? ? ? B、關于成員變量,同樣有四種方法:
public Field getDeclaredField(String name) ?獲取任意指定名字的成員
public Field[] getDeclaredFields() ? ? ? ? ?獲取所有的成員變量
public Field getField(String name) ? ? ? ? ?獲取任意public成員變量
public Field[] getFields() ? ? ? ? ? ? ? ? ?獲取所有的public成員變量
本文封裝的JdbcUtils類就是利用這種方式操作類里的私有成員變量,記得要setAccessible打開開關。如下:
Field field = cls.getDeclaredField(cols_name);
field.setAccessible(true); //打開javabean的訪問權限
field.set(resultObject, cols_value);
? ? C、關于成員函數,也有四種方法:
public Method[] getMethods() ? ?獲取所有的共有方法的集合
public Method getMethod(String name,Class<?>... parameterTypes) 獲取指定公有方法 ,
參數1:方法名 參數2:參數類型集合 ?
public Method[] getDeclaredMethods() ?獲取所有的方法
public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 獲取任意指定方法
下面是利用文中的UserInfo這個類寫的一個完成的反射例子,拿到setUsername(String username)方法,然后反射。再拿到getUsername()方法再反射,然后打印出結果:
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); 原函數里的輸入參數是什么類型,就寫什么類型.class. 如原來的setXXX需要輸入參數String,反射的時候就寫String.class.
6. JavaBean是反射的一種,反射對構造函數之類的沒任何要求,JavaBean要求這個類必須繼承Serializable即可串行化,另外構造函數必須為public.?另外,就是JavaBean在得到某個field后可以直接調用set和get,而不必再反射得到method后再執行。
? ??最后,反射是在程序運行的時候而非編譯時!!!
參考:鏈接1?鏈接2??鏈接3
? ? ?文中代碼下載鏈接:http://download.csdn.net/detail/yanzi1225627/7398533
?
總結
以上是生活随笔為你收集整理的利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包含增删改查、JavaBean反射原理,附源码)...的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。