通常java应用程序在访问数据库时,直接创建一个数据库连接,使用完毕后释放连接。
如图:
当数据库连接量小的时候这样做并无不妥,但若在访问量大的时候就显得低效了,如某网站一天访问量在1000万次,那么在这一天web应用程序与数据库就要进行等量的连接和断开操作。
为了解决这个问题,引入了数据库连接池技术(个人认为数据库连接池技术是为解决这个问题的),它是批量创建一批数据库连接,放到一个数据库连接池,在需要数据库连接时,就像这个池子拿,用完后则将数据库连接还回池子,数据库连接的维护由池负责维护,这样不管访问量如何大,程序与数据库的连接是不变的,不过当数据库连接池的连接已用完,这时又有新的连接请求,此时池中已无连接,那么就只能等待或返回异常,所以数据库连接池一次批量创建的连接数量应根据实际情况来设置。
采用数据库连接池技术如图:
根据数据库连接池工作原理来手动写一个数据库连接池,实现基本功能。
1.从池中拿出数据库连接
2.用完后还回池里
3.数据库连接的存放与维护
Code
package xgn.jdbc; import java.io.InputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.DriverManager; import java.util.LinkedList; import java.util.Properties; /*** * 数据库连接池实现类 * @author dream * */ public class JDBCPool { //存放连接的集合 private static LinkedList<Connection> dblist=new LinkedList<Connection>(); //连接池容量 private static final int number=100; static{ try{ Properties config=new Properties(); InputStream in= JDBCPool.class.getClassLoader().getResourceAsStream("config.properties"); config.load(in); for(int i=0;i<number;i++){ Connection cn= DriverManager.getConnection(config.getProperty("Connstr"),config.getProperty("user"),config.getProperty("pwd")); ConnectionProxy conn=new ConnectionProxy(cn); Connection proxycn=conn.getConnectionProxy(cn,new Class[]{Connection.class},conn); dblist.addFirst(proxycn); } }catch(Exception ex){ throw new RuntimeException(ex); } } public static void recoverConnection(Connection cn){ dblist.addFirst(cn); } public static Connection getConnection(){ if(dblist.size()<=0){ throw new RuntimeException("数据库连接池无数据库连接!"); } return dblist.removeFirst(); } public static int getConnectionNumber(){ return dblist.size(); } /*** * 数据库连接代理类 * @author dream * */ public static class ConnectionProxy implements InvocationHandler { private Object obj=null; private Object proxyobj=null; @Override public Object invoke(Object arg0, Method arg1, Object[] arg2)throws Throwable { Object ret=null;//方法返回值 if(arg1.getName()=="close"){ System.out.println("close"); JDBCPool.recoverConnection((Connection)this.proxyobj); return ret; } ret=arg1.invoke(this.obj, arg2); return ret; } public ConnectionProxy(Connection cn){ this.obj=cn; } public Connection getConnectionProxy(Connection cn,Class[] cls,InvocationHandler h){ this.proxyobj= Proxy.newProxyInstance(cn.getClass().getClassLoader(),cls,h); return (Connection)this.proxyobj; } } } |
常用的数据库连接池有:DBCP、tomcat 的数据库连接池(内部也是DBCP)、C3P0等。