Commons pool 数据库连接池实现

来源:互联网 发布:知乎图片只显示一半 编辑:程序博客网 时间:2024/05/17 07:59

 

2009-07-28

Commons pool 数据库连接池实现

 

1,首先我们要实现一个工厂类,用于处理验证,创建对象等方法。

 

 

Java代码 复制代码
  1. package net.chinacsharp.jdf.pool.connectionpool;   
  2.   
  3. import java.sql.Connection;   
  4. import java.sql.DriverManager;   
  5. import java.sql.SQLException;   
  6.   
  7. import org.apache.commons.pool.PoolableObjectFactory;   
  8.   
  9. /**  
  10.  * @author keyboardsun  mail: keyboardsun@163.com  
  11.  * @site http://www.chinacsharp.net  
  12.  */  
  13. public class SecObjectFactory implements PoolableObjectFactory {   
  14.        
  15. //  private ConnectionGetter connectionGetter = new ConnectionGetter();   
  16. //  private String CONNECTION_NAME="Sec";   
  17.     /**   
  18.      * 这里,我们在使用对象的时候,需要首先激活这个对象,但是在多线程情况下,  
  19.      * 这个对象已经被别的线程借去用了,那我们就要再建立一个对象。  
  20.      */  
  21.     public void activateObject(Object arg0) throws Exception {   
  22.         System.out.println("activateObject"+arg0);   
  23.     }   
  24.   
  25.     /**  
  26.      * 这里我们销毁这个对象。不用这个对象了,这个方法得在业务使用过程中主动调用。   
  27.      * 在调用完这个方法过后,对象已经被销毁,但是在Object pool里面还是存在这个对象的  
  28.      * 只是这个对象是null而已。所以在调用完destroyObject过后,要记得把pool清空一下。  
  29.      */  
  30.     public void destroyObject(Object arg) throws Exception {   
  31.         System.out.println("destroyObject:"+arg);   
  32.         if(((Connection)arg).isClosed()!=true){   
  33.             ((Connection)arg).close();   
  34.         }    
  35.     }   
  36.   
  37.     /**   
  38.      * 这里,在业务中第一次借对象的时候,这里要初始化一个,如果初始的都被借了,那就要继续初始  
  39.      * 这里创建的对象将被存到pool里面  
  40.      */  
  41.     public Object makeObject() throws Exception {   
  42.         Class.forName("com.mysql.jdbc.Driver").newInstance();   
  43.         Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test""root""admin");        
  44.         conn.setAutoCommit(false);   
  45.            
  46. //      Object o  = connectionGetter.getNewConnection(CONNECTION_NAME);   
  47. //      System.out.println("makeObject:"+o);   
  48.         return conn;   
  49.     }   
  50.   
  51.     /**  
  52.      * 这里,在我们使用完每个对象过后,要做的就是归还,在归还后就要调用这个方法。  
  53.      * 简单的说,在还款凭证上面签个大名  
  54.      */  
  55.     public void passivateObject(Object arg0) throws Exception {   
  56.         System.out.println("passivateObject"+arg0);   
  57.     }   
  58.   
  59.     /**   
  60.      *这个方法是验证对象,这里我们不做处理,这里在借对象和还对象的时候都要验证下的。  
  61.      */  
  62.     public boolean validateObject(Object arg) {   
  63.         System.out.println("validateObject:"+arg);   
  64.         try {   
  65.             if(((Connection)arg).isClosed()==true){   
  66.                 return false;   
  67.             } else {   
  68.                 return true;   
  69.             }   
  70.         } catch (SQLException e) {   
  71.             e.printStackTrace();   
  72.             return false;   
  73.         }   
  74.     }   
  75.   
  76. }  

 

 

2,我们要做一个pool 操作类

 

 

Java代码 复制代码
  1. package net.chinacsharp.jdf.pool.connectionpool;   
  2.   
  3.   
  4. import org.apache.commons.pool.ObjectPool;   
  5. import org.apache.commons.pool.PoolableObjectFactory;   
  6.   
  7. import org.apache.commons.pool.impl.GenericObjectPool;   
  8. import org.apache.commons.pool.impl.StackObjectPool;   
  9. import org.apache.commons.pool.impl.GenericObjectPool.Config;   
  10.   
  11. public class SecObjectPool  implements ObjectPool{   
  12.     private static SecObjectFactory factory = new SecObjectFactory();   
  13.     private static ObjectPool pool = null;   
  14.     private static GenericObjectPool.Config config = null;     
  15.   
  16.     private static boolean initFlag = false;//是否初始化   
  17.     static {   
  18.         if(!initFlag){   
  19.             config = new Config();   
  20.             config.maxActive = 2//这个属性没啥用   
  21.             config.maxIdle = 5//最大连接数,就这个有用.   
  22.             config.minIdle = 3//最少连接数 ,这个也没用,哈哈.   
  23.             pool = new GenericObjectPool(factory,config);   
  24.             initFlag = true;   
  25.         }   
  26.     }   
  27.     public Object borrowObject() throws Exception {   
  28.         return pool.borrowObject();   
  29.     }   
  30.     public void returnObject(Object arg0) throws Exception {   
  31.         pool.returnObject(arg0);   
  32.     }   
  33.     public void invalidateObject(Object arg0) throws Exception {   
  34.         pool.invalidateObject(arg0);           
  35.     }   
  36.     public void addObject() throws Exception {   
  37.         pool.addObject();   
  38.     }   
  39.     public int getNumIdle() throws UnsupportedOperationException {   
  40.         return pool.getNumIdle();   
  41.     }   
  42.     public int getNumActive() throws UnsupportedOperationException {   
  43.         return pool.getNumActive();   
  44.     }   
  45.     public void clear() throws Exception, UnsupportedOperationException {   
  46.         pool.clear();   
  47.            
  48.     }   
  49.     public void close() throws Exception {   
  50.         pool.close();   
  51.            
  52.     }   
  53.     public void setFactory(PoolableObjectFactory arg0) throws IllegalStateException, UnsupportedOperationException {   
  54.         pool.setFactory(arg0);   
  55.     }   
  56.        
  57.        
  58.   
  59. }  

 

 

3,Main 函数

 

Java代码 复制代码
  1. import java.sql.Connection;   
  2. import java.sql.PreparedStatement;   
  3. import java.sql.ResultSet;   
  4. import java.sql.SQLException;   
  5.   
  6. import net.chinacsharp.jdf.pool.connectionpool.*;   
  7. public class PoolTest {   
  8.   
  9.     /**  
  10.      * @param args  
  11.      * @throws SQLException   
  12.      */  
  13.     public static void main(String[] args) throws SQLException {   
  14.         SecObjectPool p = new SecObjectPool();   
  15.         Connection connection = null;   
  16.         try {   
  17.             connection = (Connection) p.borrowObject();   
  18.             PreparedStatement statement = null;   
  19.             statement = connection.prepareStatement("SELECT * FROM PERSON");   
  20.             ResultSet rs = statement.executeQuery();   
  21.             rs.close();   
  22.             System.out.println("================");   
  23.             p.addObject();   
  24.             System.out.println("使用中几个:"+p.getNumActive());   
  25.             System.out.println("队列中还有:"+p.getNumIdle());   
  26.             p.addObject();   
  27.             p.addObject();   
  28.             p.addObject();   
  29.             p.addObject();   
  30.             connection = (Connection) p.borrowObject();   
  31.             connection = (Connection) p.borrowObject();   
  32.             connection = (Connection) p.borrowObject();   
  33.             p.addObject();   
  34.             p.addObject();   
  35.             p.addObject();   
  36.             p.addObject();   
  37.             System.out.println("使用中几个:"+p.getNumActive());   
  38.             System.out.println("队列中还有:"+p.getNumIdle());   
  39.             System.out.println("================");   
  40.             p.returnObject(connection);   
  41.                
  42.             System.out.println("使用中几个:"+p.getNumActive());   
  43.             System.out.println("队列中还有:"+p.getNumIdle());   
  44.                
  45.             System.out.println("=====clear===========");   
  46.             p.clear();    
  47.             System.out.println("=====close===========");   
  48.             p.close();    
  49.                
  50.                
  51.         } catch (Throwable e) {   
  52.             e.printStackTrace();   
  53.             connection.close();   
  54.         }   
  55.   
  56.     }   
  57.   
  58. }  

 

 

4,输出结果

 

activateObjectcom.mysql.jdbc.Connection@147ee05
================
passivateObjectcom.mysql.jdbc.Connection@1960f05
使用中几个:1
队列中还有:1
passivateObjectcom.mysql.jdbc.Connection@1e04cbf
passivateObjectcom.mysql.jdbc.Connection@66e815
passivateObjectcom.mysql.jdbc.Connection@edc3a2
passivateObjectcom.mysql.jdbc.Connection@6e70c7
activateObjectcom.mysql.jdbc.Connection@1960f05
activateObjectcom.mysql.jdbc.Connection@1e04cbf
activateObjectcom.mysql.jdbc.Connection@66e815
passivateObjectcom.mysql.jdbc.Connection@1d63e39
passivateObjectcom.mysql.jdbc.Connection@d0a5d9
passivateObjectcom.mysql.jdbc.Connection@b8f82d
passivateObjectcom.mysql.jdbc.Connection@a6aeed
destroyObject:com.mysql.jdbc.Connection@a6aeed
使用中几个:4
队列中还有:5
================
passivateObjectcom.mysql.jdbc.Connection@66e815
destroyObject:com.mysql.jdbc.Connection@66e815
使用中几个:3
队列中还有:5
=====clear===========
destroyObject:com.mysql.jdbc.Connection@edc3a2
destroyObject:com.mysql.jdbc.Connection@6e70c7
destroyObject:com.mysql.jdbc.Connection@1d63e39
destroyObject:com.mysql.jdbc.Connection@d0a5d9
destroyObject:com.mysql.jdbc.Connection@b8f82d
=====close===========

 

通过以上结果我们可以发现,在连接池clear()的时候,调用 destroyObject 方法,我们这里把连接都关闭了

同样的道理,我们close()的时候也是如此。

 

而连接池的最大激活数目的设置是不起作用的,但是队列最多连接数那是有效果的,如果队列已经是最多了,它会把创建的或者归还的,调用 destroyObject  方法,释放对象