WEB应用中常用的数据库连接池

数据库连接池是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;
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值