程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> 利用Java針對MySql封裝的jdbc框架類JdbcUtils完整實現(包含增刪改查、JavaBean反射原理,附源碼)

利用Java針對MySql封裝的jdbc框架類JdbcUtils完整實現(包含增刪改查、JavaBean反射原理,附源碼)

編輯:MySQL綜合教程

最近看老羅的視頻,跟著完成了利用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,

6、 public <T> List<T> findMoreRefResult(String sql, List<Object> params,

下面附完整代碼:

JdbcUtils.java

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() {
		// TODO Auto-generated constructor stub
		try{
			Class.forName(DRIVER);
			System.out.println("數據庫連接成功!");

		}catch(Exception e){

		}
	}
	
	/**
	 * 獲得數據庫的連接
	 * @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();//返回查詢結果
		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()){
			//通過反射機制創建一個實例
			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的訪問權限
				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()){
			//通過反射機制創建一個實例
			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的訪問權限
				field.set(resultObject, cols_value);
			}
			list.add(resultObject);
		}
		return list;
	}

	/**
	 * 釋放數據庫連接
	 */
	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();
		}


	}

}

+----------+-------------+------+-----+---------+----------------+

是用Nvicat提前創建好的:

\

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

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() {
		// 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後會發現找不到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);

讀取每一列的屬性名字和放的值。通過屬性的名字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();

B、關於成員變量,同樣有四種方法:

public Field getDeclaredField(String name) 獲取任意指定名字的成員

本文封裝的JdbcUtils類就是利用這種方式操作類裡的私有成員變量,記得要setAccessible打開開關。如下:

Field field = cls.getDeclaredField(cols_name);

C、關於成員函數,也有四種方法:

public Method[] getMethods() 獲取所有的共有方法的集合

參數1:方法名 參數2:參數類型集合

下面是利用文中的UserInfo這個類寫的一個完成的反射例子,拿到setUsername(String username)方法,然後反射。再拿到getUsername()方法再反射,然後打印出結果:

Class clcs = UserInfo.class;

在反射方法的時候,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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved