日期:2014-05-16 浏览次数:20458 次
博客开张,把自己的一些经验做点记录.
朋友的在维护一个老的内部网站系统,数据库使用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); } } } <