Java數據庫鏈接池封裝與用法

package connection;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Vector;

import com.mysql.jdbc.Driver;

public class ConnectionPool {
	private String jdbcDriver="";	//驅動
	private String dbURL="";		//鏈接數據庫的URL
	private String userName="";	//用戶名
	private String passWord="";	//密碼
	private String testTable="";	//測試表名稱
	private int initalConNum=1;	//鏈接池的初始大小
	private int increatmentalConNum=5;		//自動增加的數量
	private int maxCon=20;		//鏈接池最大的大小
	private Vector<PooledConnection> connections=null;		//存放鏈接池中連接數據庫的向量
	
	/*
	 * 構造函數
	 * @param jdbcDriver	驅動
	 * @param dbURL			鏈接
	 * @param  username
	 * @param	password
	 */
	public ConnectionPool(String jdbcDriver,String dbURL,String username,String password){
		this.jdbcDriver=jdbcDriver;
		this.dbURL=dbURL;
		this.userName=username;
		this.passWord=password;
		
		try {
			createPool();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//返回鏈接池的初始大小
	public int getInitialCons(){
		return this.initalConNum;
	}
	
	//返回鏈接池的自動增長的大小
	public int getIncreatmentalNum(){
		return this.increatmentalConNum;
	}
	
	//返回鏈接池中最大的可用鏈接數量
	public int getMaxCons(){
		return this.maxCon;
	}
	
	//設置最大鏈接數量
	public void setMaxCons(int maxCon){
		this.maxCon=maxCon;
	}
	
	//獲取測試表的名稱
	public String getTestTable(){
		return this.testTable;
	}
	
	//設置測試表的名稱
	public void setTestTable(String testTable){
		this.testTable=testTable;
	}
	
	//建立一個數據庫鏈接池
	public synchronized void createPool() throws Exception {
		//確保鏈接池沒有建立
		//若已經建立,則保證其不爲空
		if(connections!=null){
			return;
		}
		
		//實例化數據庫驅動
		Driver driver=(Driver)Class.forName(this.jdbcDriver).newInstance();
		//註冊驅動
		DriverManager.registerDriver(driver);
		//建立保存鏈接的向量
		this.connections=new Vector<PooledConnection>();
		//根據初始化中設置的值來建立鏈接
		createConnections(this.initalConNum);
	}
	
	//建立鏈接,numConnections爲要建立的鏈接的數量
	private void createConnections(int numConnections){
		//循環建立指定數目的鏈接
		for(int i=0;i<numConnections;i++){
			//maxCon<=0表示鏈接數量沒有上限
			//判斷鏈接的數量,若已經達到最大值則推出
			if(this.maxCon>0&&this.connections.size()>=this.maxCon)
				break;
			//若知足條件則添加一個鏈接到鏈接池中
			try {
				this.connections.addElement(new PooledConnection(newConnection()));
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
				
		}
	}
	
	//建立一個新的數據庫鏈接並返回它
	private Connection newConnection() throws SQLException{
		//建立一個鏈接
		Connection conn=DriverManager.getConnection(this.dbURL, this.userName, this.passWord);
		//若是是第一次建立數據庫,即檢查數據庫,獲取此數據庫容許支持的最大鏈接數目
		if(connections.size()==0){
			DatabaseMetaData metaData=conn.getMetaData();
			int driverMaxConnections=metaData.getMaxConnections();
			if(driverMaxConnections>0&&this.maxCon>driverMaxConnections)
				this.maxCon=driverMaxConnections;
		}
		return conn;
	}
	
	//
	public synchronized PooledConnection getConnection(){
		//確保鏈接池已經被建立
		if(connections==null)
			return null;
		//獲取一個可用的數據庫鏈接
		PooledConnection conn=getFreeConnection();
		while(conn==null){		//conn==null表示沒有可用的鏈接,表示全部鏈接正在使用當中
			wait(250);
			conn=getFreeConnection();		//從新獲取鏈接,知道獲取爲止
		}
		return conn;
	}
	
	//打印鏈接池中全部鏈接的狀態
	public void print(){
		System.out.println("total connection:"+this.connections.size());
		for(int i=0;i<this.connections.size();i++){
			System.out.println(i+":"+this.connections.get(i).isBusy());
		}
	}
	
	//
	private PooledConnection getFreeConnection() {
		//從鏈接池中獲取一個可用的數據庫鏈接
		PooledConnection conn = findFreeConnection();
		
		if(conn==null){
			System.out.println("目前數據庫中沒有可用的鏈接,可用建立一些鏈接");
			createConnections(this.increatmentalConNum);
			conn=findFreeConnection();
			//若建立以後仍然得不到可用的鏈接,則返回null
			if(conn==null)
				return null;
		}
		return conn;
	}

	private PooledConnection findFreeConnection() {
		//從全部的鏈接中查找一個可用的鏈接
		for(int i=0;i<this.connections.size();i++){
			PooledConnection pc=this.connections.elementAt(i);
			if(!pc.isBusy()){
				Connection con=pc.getConnection();		//獲取其鏈接
				pc.setBusy(true);
				//測試此鏈接是否可用,若是不可用則建立一個新的鏈接
				try {
					if(!con.isValid(3000)){
						//鏈接不可用則建立一個新的鏈接
						try {
							con=newConnection();
							//同時替換掉這個不可用的鏈接對象,若建立失敗則刪除此鏈接同時遍歷下一個鏈接
							pc.setConnection(con);
						} catch (SQLException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
							connections.remove(i--);
							continue;
						}
					}
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return pc;		//找到一個可用的鏈接,退出循環
			}
		}
		return null;
	}
	
	//判斷鏈接是否可用
	public boolean isValid(Connection con){
		try {
			return con.isValid(3000);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}
	
	public void returnConnection(Connection conn){
		//確保鏈接池存在,若不存在則直接返回
		if(connections==null){
			return;
		}
		PooledConnection pConn=null;
		Enumeration<PooledConnection> enumerate=connections.elements();
		while(enumerate.hasMoreElements()){
			pConn=enumerate.nextElement();
			//先找到鏈接池中要返回的對象
			if(conn==pConn.getConnection()){
				pConn.setBusy(false);
				break;
			}
		}
	}
	
	//刷新全部鏈接池的對象
	public synchronized void refreshConnections(){
		if(connections==null){
			System.out.println("鏈接池不存在,不可以刷新!");
			return;
		}
		PooledConnection pConn=null;
		Enumeration<PooledConnection> enumerate=connections.elements();
		while(enumerate.hasMoreElements()){
			pConn=enumerate.nextElement();
			while(pConn.isBusy()){		//等待對象結束
				wait(1000);
			}
			//關閉一個鏈接,用新的鏈接來替代它
			closeConnection(pConn.getConnection());
			try {
				pConn.setConnection(newConnection());
				pConn.setBusy(false);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}
	
	//關閉池中全部鏈接並清空鏈接池
	public void closeConnectionPool() {
		if(connections==null){
			return;
		}
		PooledConnection pConn=null;
		Enumeration<PooledConnection> enumerate=connections.elements();
		while(enumerate.hasMoreElements()){
			pConn=enumerate.nextElement();
			if(pConn.isBusy()){		//等待對象結束
				wait(5000);
			}
			//關閉一個鏈接,用新的鏈接來替代它
			closeConnection(pConn.getConnection());
			//從鏈接池向量中直接刪除它
			connections.removeElement(pConn);
		}
		//置鏈接池爲空
		connections=null;
	}
	
	//關閉一個數據庫鏈接
	private void closeConnection(Connection conn){
		try {
			conn.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//使程序等待指定的秒數
	private void wait(int seconds){
		try {
			Thread.sleep(seconds);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

//內部使用的保存鏈接池對象的類
class PooledConnection{
	private Connection connection=null;
	private boolean isBusy;
	
	//構造函數,根據一個Connection構造一個PooledConnection對象
	PooledConnection(Connection connection) {
		this.connection = connection;
	}
	
	//執行查詢操做
	public ResultSet executeQuery(String sql) throws SQLException{
		return connection.createStatement().executeQuery(sql);
	}
	
	//執行更新操做
	public int executeUpdate(String sql) throws SQLException{
		return connection.createStatement().executeUpdate(sql);
	}
	
	//返回這個對象中的鏈接
	public Connection getConnection(){
		return connection;
	}

	public void setConnection(Connection con) {
		// TODO Auto-generated method stub
		this.connection=con;
	}

	public void setBusy(boolean busy) {
		// TODO Auto-generated method stub
		this.isBusy=busy;
	}

	public boolean isBusy() {
		// TODO Auto-generated method stub
		return this.isBusy;
	}
}

DBManager類:
package com.vl.sql;import java.sql.SQLException;
import com.vl.Config;import com.vl.sql.ConnectionPool.PooledConnection;public 
class DBManager {	
        private static PooledConnection conn;	
        private static ConnectionPool connectionPool;	
        private static DBManager inst;	
        public void close() {		
        try {
	    connectionPool.closeConnectionPool();
	    } catch (SQLException e) {			// TODO Auto-generated catch block
		e.printStackTrace();
	    }
	}	
	public DBManager() {		
	    if (inst != null)			
	        return;		// TODO Auto-generated constructor stub
	    String connStr = String.format("jdbc:mysql://%s:%d/%s", Config.getInstance().mysqlHost, Config.getInstance().mysqlPort,Config.getInstance().mysqlDB);
	    connectionPool = new ConnectionPool("com.mysql.jdbc.Driver", connStr, Config.getInstance().mysqlUser, Config.getInstance().mysqlPassword);		
	    try {
			connectionPool.createPool();
			inst = this;
			

		} catch (Exception e) {			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}	public static PooledConnection getConnection() {		if (inst == null)			new DBManager();		try {
			
			conn = connectionPool.getConnection();
			
		} catch (SQLException e) {			// TODO Auto-generated catch block
			e.printStackTrace();
		}		return conn;
	}	public static void main(String[] args) {

	}

}

用法:
                String sql = "....";
		ResultSet rs;
		PooledConnection conn = null;		try {
			conn = DBManager.getConnection();
			rs = conn.executeQuery(sql);			if (rs.next())			return rs.getInt(1);
		} catch (SQLException e) {		// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			conn.close();
		}		return 0;
相關文章
相關標籤/搜索