数据库连接池是WEB应用中必不可少的东西,这是我个人最近参照别人代码写的自己的数据库连接池。
package com.bpcrm.kevin.util.DB_utill.connection_pool;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Enumeration;
import java.util.Vector;
/**
* 连接池对象
* @author kevin.wangwei
* 2009-11-17
*/
public class ConnectionPool {
/**驱动名称*/
private String jdbcDriver;
/**驱动url*/
private String url;
/**用户名称*/
private String userName;
/**用户密码*/
private String password;
/**初始化连接数*/
private int initConnections=10;
/**连接池自动增长连接数、默认为:5*/
private int increamentConnections=5;
/**连接池最大连接数*/
private int maxConnections=50;
/**存放连接对象的数组*/
private Vector connections=null;
/**测试用表*/
private String testTable;
/**
* 默认构造函数
* 将默认构造函数设为私有
* 防止在无用户名和密码的情况下创建连接池对象
*/
private ConnectionPool(){};
/**
* 自定义构造函数
* @param jdbcDriver 驱动名
* @param url 数据库URL
* @param userName 用户名
* @param password 密码
*/
public ConnectionPool(String jdbcDriver,String url,String userName,String password){
this.jdbcDriver=jdbcDriver;
this.url=url;
this.userName=userName;
this.password=password;
}
/**
* 设置测试表名称
* @param testTable 测试表名称
*/
public void setTestTable(String testTable) {
this.testTable = testTable;
}
/**
* 获得连接池自动增长大小
* @return 自动增长大小
*/
public int getIncreamentConnections() {
return increamentConnections;
}
/**
* 设置连接池自动增长大小
* @param increamentConnections 自动增长大小
*/
public void setIncreamentConnections(int increamentConnections) {
this.increamentConnections = increamentConnections;
}
/**
* 获得连接池最大连接数
* @return 最大连接数
*/
public int getMaxConnections() {
return maxConnections;
}
/**
* 设置连接池最大连接数
* @param maxConnections 最大连接数
*/
public void setMaxConnections(int maxConnections) {
this.maxConnections = maxConnections;
}
/**
* 获得连接池初始化连接数
* @return 初始化连接数
*/
public int getInitConnections() {
return initConnections;
}
/**
* 设置连接池初始化连接数
* @param initConnections 初始化连接数
*/
public void setInitConnections(int initConnections) {
this.initConnections = initConnections;
}
/**
* 使程序等待给定的毫秒数
* @param mseconds 毫秒数
*/
private void wait(int mseconds ){
try {
Thread.sleep(mseconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 刷新连接池对象
* @throws Exception 抛出异常
*/
public synchronized void refreshConnections()throws Exception{
if(connections==null){
System.out.println("连接池不存在,无法刷新连接!");
return;
}
PooledConnection connection=null;
Enumeration enumer=connections.elements();
while(enumer.hasMoreElements()){
connection=(PooledConnection)enumer.nextElement();
if(connection.isBusy()){
this.wait(5000);
}
closeConnection(connection.getConn());//调用closeConnection(Connection conn)关闭数据库连接;
connection.setConn(newConnection());
connection.setBusy(false);
}
}
/**
* 关闭连接池对象
* @throws Exception 抛出异常
*/
public synchronized void closeConnectionPool()throws Exception{
if(connections==null){
System.out.println("连接池已经关闭");
return;
}
PooledConnection connection=null;
Enumeration enumer=connections.elements();
while(enumer.hasMoreElements()){
connection =(PooledConnection)enumer.nextElement();
if(connection.isBusy()){
wait(5000);
}
closeConnection(connection.getConn());//调用closeConnection(Connection conn)关闭数据库连接;
}
connections.clear();
connections=null;
}
/**
* 关闭数据库连接
* @param con 数据库连接
*/
private void closeConnection(Connection con){
try {
con.close();
} catch (SQLException e) {
System.err.print(e.getMessage());
}
}
/**
* 创建一个新的数据库连接对象
* @return 数据库连接
* @throws Exception 抛出异常
*/
private Connection newConnection()throws Exception{
Connection con=DriverManager.getConnection(url,userName,password);
if(connections.size()==0){
DatabaseMetaData metadata=con.getMetaData();
int driverMaxConnection=metadata.getMaxConnections();//如果数据库最大连接数为0,表示该数据库最大连接数没有限制
if(driverMaxConnection>0&&this.maxConnections>driverMaxConnection){
this.maxConnections=driverMaxConnection;
}
}
return con;
}
/**
* 根据指定的连接数创建连接池的连接的个数
* @param numConnections 连接数
* @throws Exception 抛出异常
*/
@SuppressWarnings("unchecked")
private void createConnections(int numConnections)throws Exception{
for(int i=0;i<numConnections;i++){
if(this.maxConnections>0&&this.connections.size()>=this.maxConnections){
break;
}
try {
connections.addElement(new PooledConnection(newConnection()));
} catch (Exception e) {
System.err.println("创建数据库连接失败");
throw new Exception();
}
System.out.println("创建数据库连接个数为:"+i);
}
}
/**
* 创建连接池对象
* @throws Exception
*/
public synchronized void createPool()throws Exception{
if(connections!=null){
return;//如果连接数已存在则不用创建
}
Driver driver=(Driver)(Class.forName(this.jdbcDriver)).newInstance();
DriverManager.registerDriver(driver);
connections =new Vector();
createConnections(this.initConnections);//根据初始化连接数的数目,创建连接池的连接数目
System.out.println("数据库连接池创建成功!");
}
/**
* 将指定数据库连接设为空闲状态
* @param conn 数据库连接
* @throws Exception 抛出异常
*/
public void returnConnection(Connection conn)throws Exception{
if(connections==null){
System.out.println("连接池不存在,无法获得连接对象");
return;
}
PooledConnection poolConnection=null;
Enumeration eum=connections.elements();
while(eum.hasMoreElements()){
poolConnection=(PooledConnection)eum.nextElement();
if(conn==poolConnection.getConn()){
poolConnection.setBusy(false);
break;
}
}
}
/**
* 测试从数据库连接池中获得的数据库连接对是否可用
* @param conn 数据库连接
* @return boolean 是否可用
*/
private boolean testConnection(Connection conn){
try {
if(testTable.equals(" ")){
conn.setAutoCommit(true);
}else{
Statement sta=conn.createStatement();
sta.execute("select count(*) from "+testTable);
}
} catch (SQLException e) {
closeConnection(conn);
return false;
}
return true;
}
/**
* 查找空闲的连接(也就是可用连接)
* @return 数据库连接
*/
private Connection findFreeConnection(){
Connection conn=null;
PooledConnection poolConn=null;
Enumeration enu=connections.elements();
while(enu.hasMoreElements()){
poolConn=(PooledConnection)enu.nextElement();
if(!poolConn.isBusy()){
conn=poolConn.getConn();
poolConn.setBusy(true);
if(!testConnection(conn)){
try {
conn=newConnection();
} catch (Exception e) {
System.err.println(e.getMessage());
return null;
}
poolConn.setConn(conn);
}
break;
}
}
return conn;
}
/**
* 获得可用连接
* @return 可用数据库连接
* @throws Exception 抛出异常
*/
private Connection getFreeConnection()throws Exception{
Connection conn=findFreeConnection();
if(conn==null){//如果没有找到则创建连接数获得连接对象
createConnections(this.increamentConnections);
conn=findFreeConnection();
if(conn==null){
return null;
}
}
return conn;
}
/**
* 此方法供外部调用来或得连接对象,支持多线程访问
* @return 可用的连接对象
* @throws Exception 抛出异常
*/
public synchronized Connection getConnection()throws Exception{
if(connections==null){
return null;
}
Connection conn=getFreeConnection();
while(conn==null){
wait(250);
conn=getFreeConnection();
}
return conn;
}
}
package com.bpcrm.kevin.util.DB_utill.connection_pool;
import java.sql.Connection;
/**
* 将数据库链接包装为一个对象
* @author kevin.wangwei
* 2009-11-17
*/
public class PooledConnection {
/**连接属性*/
private Connection conn=null;
/**该连接是否空闲*/
private boolean busy=false;
/**
* 设置一个连接
* @param con 连接对象
*/
public PooledConnection(Connection con){
this.conn=con;
}
/**
* 获得该连接对象的空闲属性
* @return 该连接是否空闲
*/
public boolean isBusy() {
return busy;
}
/**
* 设置该连接的空闲属性
* @param busy 空闲值
*/
public void setBusy(boolean busy) {
this.busy = busy;
}
/**
* 获得该连接对象的数据库连接
* @return 数据库连接
*/
public Connection getConn() {
return conn;
}
/**
* 设置该连接对象的数据库连接
* @param conn 数据库连接
*/
public void setConn(Connection conn) {
this.conn = conn;
}
}