日期:2014-05-16  浏览次数:20466 次

用apache.commons.pool 实现Access数据库连接池

博客开张,把自己的一些经验做点记录.

朋友的在维护一个老的内部网站系统,数据库使用access,该系统访问量一多经常会报sql错误,提示客户端过多问题.

查看了系统代码,发现这个系统的数据库连接代码每次都是重新创建的.

    public static Connection getConn() throws ClassNotFoundException,
            SQLException {
        Connection conn = null;
        String driver = "jdbc:odbc:driver={microsoft access driver (*.mdb)};dbq=d:\\data.mdb";
               Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");   
        conn = DriverManager.getConnection(driver);
        return conn;
    }

?这样的问题就很严重,首先就是无法控制并发的数据库操作,导致并发高于一定量后access数据库直接报错提示客户端过多。

其次就是数据库操作效率低下,每次建立连接和释放连接的效率很低。

解决这个问题需要对数据库连接上加入连接池,保证数据库连接安全可控,高效。

由于是老系统要求改动的代码尽量少,google了一把也没找到可以直接使用access文件作为数据库连接池的代码,就自己动手写了一个。

该连接池只要依赖apache.commons.pool 开源组件。

首先实现一个数据库连接创建,销毁的工厂类DBConnectFactory该类实现了接口org.apache.commons.pool.PoolableObjectFactory

package base;

import java.sql.Connection;
import java.sql.DriverManager;

import org.apache.commons.pool.PoolableObjectFactory;

/**
 * 数据库连接工厂类
 *
 * @author binda.mabd
 * @version 1.0
 * @date 2009-4-3
 */
public class DBConnectFactory implements PoolableObjectFactory {
	private int count =0 ;
	private String driver ;
	private String className;
	public DBConnectFactory(String className,String driver){
		this.className = className;
		this.driver = driver;
	}
	/**
	 * 对象初始化后加入池的时候使用,设置对象为可用状态。
	 */
	public void activateObject(Object arg0) throws Exception {
	//直接加入
		
	}
	/**
	 * 对象销毁方法
	 */
	public void destroyObject(Object arg0) throws Exception {
		 System.err.println("destroyObject Object " + arg0.getClass().getName());
		if(arg0!=null){
			Connection con = (Connection)arg0;
			try{
			con.close();
			 count --;
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	/**
	 * 对象创建方法
	 */
	public Object makeObject() throws Exception {
		try {
			Class.forName(className);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}  
		  count ++;
		   return  DriverManager.getConnection(driver);

	}
	/**
	 * 非创建对象回到池的时使用,设置对象为可用.
	 */
	public void passivateObject(Object arg0) throws Exception {
		Connection con = (Connection)arg0;
		//如果非自动commit类型连接,强制comit后返回连接池
		if(!con.getAutoCommit()){
			con.commit();
		}

	}
	/**
	 * 状态检查对象是否可用
	 */
	public boolean validateObject(Object arg0) {
		
		try{
		Connection con = (Connection)arg0;
		return con!=null&&!con.isClosed();
		}catch(Exception e){
		return false ;
		}
				
	}

}

?

?

?

有了DBConnectFactory工厂类,就可以通过org.apache.commons.pool.impl.GenericObijectPool 来创建一个自定义的连接池.

package base;

import java.sql.Connection;

import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;

public class SimpleAccessPool {
	
    GenericObjectPool pool  = null; 
    PoolableObjectFactory factory = null;
    public SimpleAccessPool (String accessFilePath){
		  String className = "sun.jdbc.odbc.JdbcOdbcDriver"	;
		  String driver = "jdbc:odbc:driver={microsoft access driver (*.mdb)};dbq=";
		  driver = driver + accessFilePath;
    	factory = new DBConnectFactory(className,driver);
    	
    }
    public void init(){
        pool = new GenericObjectPool(factory);
        //最大连接数
         pool.setMaxActive(30); 
         //最大空闲连接数
         pool.setMaxIdle(20);
              //连接等待1分钟
         pool.setMaxWait(60000);
    }
    /** 获得连接*/
     public Connection getConnection() {
    	try {
			return	(Connection) pool.borrowObject();
			
		}catch (Exception e){
			 e.printStackTrace();
				throw new RuntimeException("get connect error",e);
		}
    	
     }
     /**释放连接*/
     public void relaseConnection(Connection con){
         try {
			pool.returnObject(con);
		} catch (Exception e) {
			  e.printStackTrace();
			throw new RuntimeException("relase connect error",e);
		}
     }
	
	}
<