随着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的示例,还有许多可以完善的地方,如用计时器记录连接池的时间,设置超时时限等等。