`
lancelot_WT
  • 浏览: 4476 次
  • 性别: Icon_minigender_1
  • 来自: 丽江
文章分类
社区版块
存档分类
最新评论

DBCP——数据库连接池理解

阅读更多

       随着Internet的发展B/S的三层结构逐渐取代了C/S的两层结构,在WEB中运用越来越广泛。其中JDBC( Java DataBase Connction)是连接Java程序与数据库的桥梁,让程序员可以在Java代码里就可以进行数据库的操作。

一般来说在java里进行数据库的操作主要有以下几个步骤:

(1)装载数据库驱动;

(2)通过JDBC连接数据库;

(3)访问数据库,执行sql语句;

(4)断开数据库连接。

每进行一次数据库访问的操作就要进行数据库的连接操作,这是比较耗费时间的一步,

每次连接操作都大约耗时0.5s——1s。在进行少量的数据库操作时这样的速度还能接受,但是在WEB应用中,面对的是几百几千甚至上万的用户,每个用户连接一次数据库都要耗时这么多,显然不能让人接受,所以需要对数据库连接进行有效管理,DBCP(DataBase Conntion Pool)便应运而生。

DBCP的基本思想就是在虚拟的“池”中先放入一些建立好的连接像,当要进行数据库访

问时,直接从“池”中拿出连接来使用,而不是去创建一个连接对象,当访问完成时又放回到“池”中,这样便节省了数据库连接的时间。DBCP的模型由一个连接池类和一个连接池管理类构成,示例如下:

package cn.wutong.DBCP;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;

/**
 * 数据库连接池类
 * @author 吴同
 *
 */
public class DBConnectionPool {
	 private int inUsed=0;    //使用的连接数
	 private String poolName;//连接池的名字
	 private ArrayList<Connection> freeConnections = new ArrayList();//容器,空闲连接
	 //private int minConn;     //最小连接数
	 private int maxConn;     //最大连接
	 private String password; //密码
	 private String url;      //数据库连接地址
	 private String driver;   //驱动
	 private String userName;     //用户名
	 public DBConnectionPool(String url,String driver,String userName,String password){
		 this.url=url;
		 this.driver=driver;
		 this.userName=userName;
		 this.password=password;
	 }//创建对象时可以输入其数据库连接的参数
	 public int getInUsed() {
		return inUsed;
	}
	 //得到所有的空闲连接
	public ArrayList getFreeConnections() {
		return freeConnections;
	}
	public void setPoolName(String poolName) {
		this.poolName = poolName;
	}
	public String getPoolName(){
		return this.poolName;
	}
//	public int getMinConn() {
//		return minConn;
//	}
//	public void setMinConn(int minConn) {
//		this.minConn = minConn;
//	}
	public int getMaxConn() {
		return maxConn;
	}
	public void setMaxConn(int maxConn) {
		this.maxConn = maxConn;
	}
//创建连接,内部方法,不能在外部调用
	private  Connection creatConnection(){
		Connection conn=null;
	try {
		Class.forName(driver);
		try {
		conn=DriverManager.getConnection(url, userName, password);
		System.out.println("DBConnectionPool-->creatConnection()-->创建了一个数据库连接");
		} catch (SQLException e) {
			System.out.println("DBConnectionPool-->creatConnection()-->数据库连接错误");
			e.printStackTrace();
		}
	} catch (ClassNotFoundException e) {
		System.out.println("没有找到这种数据库的驱动");
		e.printStackTrace();
	}
	return conn;
}
	//得到连接的方法
	public synchronized  Connection getConnention(){
		Connection conn=null;
		if(maxConn>inUsed){
			if(this.freeConnections.size()>0){
				conn=this.freeConnections.get(0);//已经创建过连接,直接从空闲连接队列里得到
				freeConnections.remove(0);//从空闲连接队列中去除
				System.out.println("DBConnectionPool-->getConnention()-->从空闲连接中得到一个连接");
				if(conn==null){//如果得到的是空则说明所有创建的连接都已被用了
					System.out.println("DBConnectionPool-->getConnention()-->得到的连接为空重新得到");
					conn=getConnention();// 重新得到连接
				}
			}else{//如果没有创建过连接则创建一个
				conn=creatConnection();
			}
		}
		if(conn!=null){
			inUsed++;
			System.out.println("DBConnectionPool-->getConnention()-->得到了连接对象");
		}else{
			System.out.println("DBConnectionPool-->getConnention()-->超过连接范围,没有得到连接对象");
		}
		return conn;
	}
	//释放一个连接
	public synchronized void freeConnection(Connection conn){
		freeConnections.add(conn);
		inUsed--;
		}
	//释放所有连接
	public synchronized void realseAllConnections(){
		java.util.Iterator iter=this.freeConnections.iterator();
		while(iter.hasNext()){
			Connection conn=(Connection)iter.next();
			try {
				conn.close();
			} catch (SQLException e) {
				System.out.println("DBConnectionPool-->realseAllConnections()-->连接关闭错误");
				e.printStackTrace();
			}
		}
		freeConnections.clear();//空闲连接队列清空
	}
}

 

package cn.wutong.DBCP;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * 数据连接池管理类
 * @author 吴同
 *
 */
public class DBConnectionManager {
	private static DBConnectionManager instance;//唯一的数据连接管理对象
	 private static int clients;//客户数量
	private ArrayList drivers = new ArrayList();//容器,存放数据库驱动程序
	private HashMap<String,DBConnectionPool> pools = new HashMap ();//以name/value的形式存取连接池对象的名字及连接池对象
	private DBConnectionManager(){
		init();
	}//私有构造函数,在其中调用初始化函数init()
	//如果唯一的实例instance已经创建,直接返回这个实例;否则,调用私有构造函数,创建连接池管理类的唯一实例
	public static synchronized  DBConnectionManager getInstance(){
		if(instance==null){
			instance=new DBConnectionManager();
		}
		System.out.println("DBConnectionManager->getInstance()->得到了数据连接吃管理对象");
		return instance;
	}
	// 释放一个连接,name是一个连接池对象的名字
	public void freeConnection(String poolName, Connection con){
		DBConnectionPool pool=pools.get(poolName);
		if(pool!=null){
			pool.freeConnection(con);
			System.out.println("DBConnectionManager->freeConnection()->释放了"+poolName+"中的一个连接");
		}else{
			System.out.println("DBConnectionManager->freeConnection()->没有这个连接池");
		}
	}
	//从名字为name的连接池对象中得到一个连接
	 public Connection getConnection(String poolName){
		 Connection con=null;
		 DBConnectionPool pool=pools.get(poolName);
		 if(pool!=null){
			 con=pool.getConnention();
	 }else{
		 System.out.println("DBConnectionManager->getConnection()->没有这个连接池");
	 }
		 if(con==null){
			 System.out.println("DBConnectionManager->getConnection()->没有得到连接对象");
		 }else  System.out.println("DBConnectionManager->getConnection()->得到了连接对象");
		return con;
	 }
	//从名字为name的连接池对象中取得一个连接,time是等待时间
	//public Connection getConnection(String name, long time){}
	//释放所有资源
	public synchronized void release(){
	java.util.Set keySet=pools.keySet();
	java.util.Iterator iter=keySet.iterator();
	while(iter.hasNext()){
		DBConnectionPool pool=pools.get(iter.next());
		pool.realseAllConnections();
	}
	pools.clear();
	System.out.println("DBConnectionManager->release()->释放了所有连接池");
	}
	//创建一个连接池
	private void createPools(String url,String driver,String userName,String password,int maxConn,String poolName){
		DBConnectionPool pool=new DBConnectionPool(url,driver,userName,password);
		pool.setMaxConn(maxConn);
		pool.setPoolName(poolName);
		pools.put(poolName, pool);
		System.out.println("DBConnectionManager->createPools()->创建了一个"+poolName+"的连接池");
	}
	//初始化连接池管理类的唯一实例,由私有构造函数调用
	private void init(){}
	//装载驱动
	private void loadDriver(){}
}

 

 

 

 在WEB中使用时,在一个servlet初始化时(init方法被调用)时得到数据库连接池管理对象,在service方法中使用数

据库连接池,进行数据库操作,在destroy方法中释放所有资源。

本篇文章只是一个DBCP的示例,还有许多可以完善的地方,如用计时器记录连接池的时间,设置超时时限等等。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics