`
laorer
  • 浏览: 434565 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

数据库连接池java实现小结

阅读更多
数据库连接池java实现小结
 
Chinageren.com 2004-8-25 <script language="javascript" src="/Article/GetHits.asp?ArticleID=27526" type="text/javascript"></script> 转载注明:www.chinageren.com
<script language="javascript" src="/my/wtop2.js" type="text/javascript"></script>
<script type="text/javascript">var arrBaiduCproConfig=new Array();arrBaiduCproConfig['uid'] = 72095;arrBaiduCproConfig['n'] = 'chinagerencpr';arrBaiduCproConfig['tm'] = 30;arrBaiduCproConfig['cm'] = 76;arrBaiduCproConfig['um'] = 0;arrBaiduCproConfig['rad'] = 1;arrBaiduCproConfig['w'] = 250;arrBaiduCproConfig['h'] = 250;arrBaiduCproConfig['bd'] = '#FFFFFF';arrBaiduCproConfig['bg'] = '#ffffff';arrBaiduCproConfig['tt'] = '#0000ff';arrBaiduCproConfig['ct'] = '#000000';arrBaiduCproConfig['url'] = '#666666';arrBaiduCproConfig['bdl'] = '#ffffff';arrBaiduCproConfig['wn'] = 1;arrBaiduCproConfig['hn'] = 5;arrBaiduCproConfig['ta'] = 'center';arrBaiduCproConfig['tl'] = 'bottom';arrBaiduCproConfig['bu'] = 0;</script> <script src="http://cpro.baidu.com/cpro/ui/ui.js" type="text/javascript"></script> <script type="text/javascript"><!----></script>

       因为工作需要要使用到连接池,所以拜读了互联网上众多前辈的文章,学了不少经验,这里想做一个小结,加上自己的想法和在一起,希望能给大家一些帮助。

目的:

  • 消除数据库频繁连接带来的开销和瓶颈。

解决方案:

  • 不过多的限制用户的使用,既不能太多的要求用户按规定的方法得到和使用数据库连
  • 尽量保持用户的习惯

目前的很多方法都是要求用户只能按规定方法使用连接,不能使用直接关闭数据连接的方法。解决办法就是使用代理类,来中间解决。可以参考http://www-900.ibm.com/developerWorks/cn/java/l-connpoolproxy/index.shtml

  • 能维护连接的正常状态

因为针对数据库连接创建的资源,如果不能及时的释放,就会影响下一次数据连接的使用。例如在sql 2k中,一个连接不同创建多条Statement否则操作时会有数据连接占线的异常,所以必须在归还连接以后释放这些资源。

   //判断是使用了createStatement语句
   if (CREATESTATE.equals(method.getName()))
   {
    obj = method.invoke(conn, args);
    statRef = (Statement)obj;//记录语句
    return obj;
   }

   //判断是否调用了close的方法,如果调用close方法则把连接置为无用状态
   if(CLOSE.equals(method.getName()))
   {
    //设置不使用标志
    setIsFree(false);
    //检查是否有后续工作,清除该连接无用资源
    if (statRef != null)
     statRef.close();
    if (prestatRef != null)
     prestatRef.close();
    return null;
   }

  • 正确保护类不被违例使用

一个考虑就是不能让用户随便使用代理类,而只能自己使用,一个就是用内部私有类,一个就是使用只有指定类才能调用的标志。我的实现就是采用后者。

 /**
  * 创建连接的工厂,只能让工厂调用
  * @param factory 要调用工厂,并且一定被正确初始化
  * @param param 连接参数
  * @return 连接
  */
 static public _Connection getConnection(ConnectionFactory factory, ConnectionParam param)
 {
  if (factory.isCreate())//判断是否正确初始化的工厂
  {
   _Connection _conn = new _Connection(param);
   return _conn;
  }
  else
   return null;
 }
  • 提供良好的用户接口,简单实用

使用静态方法创建工厂,然后来得到连接,使用完全和普通的Connection方法一样,没有限制。同时为了方便,设置了连接参数类和工厂参数类。

  •  ConnectionParam param = new ConnectionParam(driver,url,user,password);
      ConnectionFactory cf = null;//new ConnectionFactory(param, new FactoryParam());
      try{
       cf = new ConnectionFactory(param,new FactoryParam());
       Connection conn1 = cf.getFreeConnection();
       Connection conn2 = cf.getFreeConnection();
       Connection conn3 = cf.getFreeConnection();
       Statement stmt = conn1.createStatement();
       ResultSet rs = stmt.executeQuery("select * from requests");
       if (rs.next())
       {
        System.out.println("conn1 y");  
       }
       else
       {
        System.out.println("conn1 n");  
       } 
       stmt.close();
       conn1.close();  
  • 为了实现连接池的正常运作,使用了单态模式

 /**
  * 使用指定的参数创建一个连接池
  */
 public ConnectionFactory(ConnectionParam param, FactoryParam fparam)
  throws SQLException
 {
  //不允许参数为空
  if ((param == null)||(fparam == null))
   throw new SQLException("ConnectionParam和FactoryParam不能为空");
  if (m_instance == null)
  {
   synchronized(ConnectionFactory.class){
    if (m_instance == null)
    {
     //new instance
     //参数定制
     m_instance = new ConnectionFactory();
     m_instance.connparam = param;
     m_instance.MaxConnectionCount = fparam.getMaxConn();
     m_instance.MinConnectionCount = fparam.getMinConn();
     m_instance.ManageType = fparam.getType();
     m_instance.isflag = true;
     //初始化,创建MinConnectionCount个连接
     System.out.println("connection factory 创建!");
     try{
      for (int i=0; i < m_instance.MinConnectionCount; i++)
      {
       _Connection _conn = _Connection.getConnection(m_instance, m_instance.connparam);
       if (_conn == null) continue;
       System.out.println("connection创建");
       m_instance.FreeConnectionPool.add(_conn);//加入空闲连接池
       m_instance.current_conn_count ++;
       //标志是否支持事务
       m_instance.supportTransaction = _conn.isSupportTransaction();    
      }
     }
     catch(Exception e)
     {
      e.printStackTrace();
     }
     //根据策略判断是否需要查询
     if (m_instance.ManageType != 0)
     {
      Thread t = new Thread(new FactoryMangeThread(m_instance));
      t.start();
     } 
    }
   }
  }
 }
 

  • 连接池的管理

对于连接池的管理,我是设想使用静态管理和动态管理两种策略,设置了最大限制,和恒定的连接数。使用了2个池,一个空闲池,一个使用池。静态就是使用的时候发现空闲连接不够再去检查。动态就是使用了一个线程定时检查。

 //根据策略判断是否需要查询
     if (m_instance.ManageType != 0)
     {
      Thread t = new Thread(new FactoryMangeThread(m_instance));
      t.start();
     }
 //连接池调度线程
public class FactoryMangeThread implements Runnable {
 ConnectionFactory cf = null;
 long delay = 1000;
 public FactoryMangeThread(ConnectionFactory obj)
 {
  cf = obj;
 }
 /* (non-Javadoc)
  * @see java.lang.Runnable#run()
  */
 public void run() {
  while(true){
   try{
    Thread.sleep(delay);
   }
   catch(InterruptedException e){}
   System.out.println("eeeee");
   //判断是否已经关闭了工厂,那就退出监听
   if (cf.isCreate())
    cf.schedule();
   else
    System.exit(1);
  }
 }
}

最后给出完整的源代码:

 


 

_Connectio.java

package scut.ailab.connectionpool;
import java.lang.reflect.*;
import java.sql.*;
/**
 * @author youyongming
 * 定义数据库连接的代理类
 */
public class _Connection implements InvocationHandler {
 //定义连接
 private Connection conn = null;
 //定义监控连接创建的语句
 private Statement statRef = null;
 private PreparedStatement prestatRef = null;
 //是否支持事务标志
 private boolean supportTransaction = false;
 //数据库的忙状态
 private boolean isFree = false;
 //最后一次访问时间
 long lastAccessTime = 0;
 //定义要接管的函数的名字
 String CREATESTATE = "createStatement";
 String CLOSE = "close";
 String PREPARESTATEMENT = "prepareStatement";
 String COMMIT = "commit";
 String ROLLBACK = "rollback";
 /**
  * 构造函数,采用私有,防止被直接创建
  * @param param 连接参数
  */
 private _Connection(ConnectionParam param) {
  //记录日至
  
  try{
   //创建连接
   Class.forName(param.getDriver()).newInstance();
   conn = DriverManager.getConnection(param.getUrl(),param.getUser(), param.getPassword());   
   DatabaseMetaData dm = null;
   dm = conn.getMetaData();
   //判断是否支持事务
   supportTransaction = dm.supportsTransactions();
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
 }

 /* (non-Javadoc)
  * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
  */
 public Object invoke(Object proxy, Method method, Object[] args)
  throws Throwable {
   Object obj = null;
   //判断是否调用了close的方法,如果调用close方法则把连接置为无用状态
   if(CLOSE.equals(method.getName()))
   {
    //设置不使用标志
    setIsFree(false);
    //检查是否有后续工作,清除该连接无用资源
    if (statRef != null)
     statRef.close();
    if (prestatRef != null)
     prestatRef.close();
    return null;
   }
   //判断是使用了createStatement语句
   if (CREATESTATE.equals(method.getName()))
   {
    obj = method.invoke(conn, args);
    statRef = (Statement)obj;//记录语句
    return obj;
   }
   //判断是使用了prepareStatement语句
   if (PREPARESTATEMENT.equals(method.getName()))
   {
    obj = method.invoke(conn, args);
    prestatRef = (PreparedStatement)obj;
    return obj;
   }
   //如果不支持事务,就不执行该事物的代码
   if ((COMMIT.equals(method.getName())||ROLLBACK.equals(method.getName())) && (!isSupportTransaction()))
    return null;   
   obj = method.invoke(conn, args); 
   //设置最后一次访问时间,以便及时清除超时的连接
   lastAccessTime = System.currentTimeMillis();
   return obj;
 }
 /**
  * 创建连接的工厂,只能让工厂调用
  * @param factory 要调用工厂,并且一定被正确初始化
  * @param param 连接参数
  * @return 连接
  */
 static public _Connection getConnection(ConnectionFactory factory, ConnectionParam param)
 {
  if (factory.isCreate())//判断是否正确初始化的工厂
  {
   _Connection _conn = new _Connection(param);
   return _conn;
  }
  else
   return null;
 }
 
 public Connection getFreeConnection() {
  //返回数据库连接conn的接管类,以便截住close方法
  Connection conn2 = (Connection)Proxy.newProxyInstance(
   conn.getClass().getClassLoader(),
   conn.getClass().getInterfaces(),this);
  return conn2;
 }
 /**
  * 该方法真正的关闭了数据库的连接
  * @throws SQLException
  */
 void close() throws SQLException{
  //由于类属性conn是没有被接管的连接,因此一旦调用close方法后就直接关闭连接
  conn.close();
 }
   
 public void setIsFree(boolean value)
 {
  isFree = value;
 }
 
 public boolean isFree() {
  return isFree;
 } 
 /**
  * 判断是否支持事务
  * @return boolean
  */
 public boolean isSupportTransaction() {
  return supportTransaction;
 } 
}

 


ConnectionFactory.java

 package scut.ailab.connectionpool;
/**
 * @author youyongming
 *
 */
import java.util.LinkedHashSet;
import java.sql.*;
import java.util.Iterator;
public class ConnectionFactory {
 private static ConnectionFactory m_instance = null;
 //在使用的连接池
 private LinkedHashSet ConnectionPool = null;
 //空闲连接池
 private LinkedHashSet FreeConnectionPool = null;
 //最大连接数
 private int MaxConnectionCount = 4;
 //最小连接数
 private int MinConnectionCount = 2;
 //当前连接数
 private int current_conn_count = 0;
 //连接参数
 private ConnectionParam connparam = null;
 //是否创建工厂的标志
 private boolean isflag = false;
 //是否支持事务
 private boolean supportTransaction = false;
 //定义管理策略
 private int ManageType = 0;
 private ConnectionFactory() {
  ConnectionPool = new LinkedHashSet();
  FreeConnectionPool = new LinkedHashSet();
 }
 
 /**
  * 使用指定的参数创建一个连接池
  */
 public ConnectionFactory(ConnectionParam param, FactoryParam fparam)
  throws SQLException
 {
  //不允许参数为空
  if ((param == null)||(fparam == null))
   throw new SQLException("ConnectionParam和FactoryParam不能为空");
  if (m_instance == null)
  {
   synchronized(ConnectionFactory.class){
    if (m_instance == null)
    {
     //new instance
     //参数定制
     m_instance = new ConnectionFactory();
     m_instance.connparam = param;
     m_instance.MaxConnectionCount = fparam.getMaxConn();
     m_instance.MinConnectionCount = fparam.getMinConn();
     m_instance.ManageType = fparam.getType();
     m_instance.isflag = true;
     //初始化,创建MinConnectionCount个连接
     System.out.println("connection factory 创建!");
     try{
      for (int i=0; i < m_instance.MinConnectionCount; i++)
      {
       _Connection _conn = _Connection.getConnection(m_instance, m_instance.connparam);
       if (_conn == null) continue;
       System.out.println("connection创建");
       m_instance.FreeConnectionPool.add(_conn);//加入空闲连接池
       m_instance.current_conn_count ++;
       //标志是否支持事务
       m_instance.supportTransaction = _conn.isSupportTransaction();    
      }
     }
     catch(Exception e)
     {
      e.printStackTrace();
     }
     //根据策略判断是否需要查询
     if (m_instance.ManageType != 0)
     {
      Thread t = new Thread(new FactoryMangeThread(m_instance));
      t.start();
     } 
    }
   }
  }
 }
 
 /**
  * 标志工厂是否已经创建
  * @return boolean
  */ 
 public boolean isCreate()
 {
  return m_instance.isflag;
 }
 
 /**
  * 从连接池中取一个空闲的连接
  * @return Connection
  * @throws SQLException
  */
 public synchronized Connection getFreeConnection()
  throws SQLException
 {
  Connection conn = null;
  //获取空闲连接
  Iterator iter = m_instance.FreeConnectionPool.iterator();
  while(iter.hasNext()){
   _Connection _conn = (_Connection)iter.next();
   //找到未用连接
   if(!_conn.isFree()){
    conn = _conn.getFreeConnection();
    _conn.setIsFree(true);
    //移出空闲区
    m_instance.FreeConnectionPool.remove(_conn);
    //加入连接池 
    m_instance.ConnectionPool.add(_conn);   
    break;
   }
  }
  //检查空闲池是否为空
  if (m_instance.FreeConnectionPool.isEmpty())
  {
   //再检查是否能够分配
   if (m_instance.current_conn_count < m_instance.MaxConnectionCount)
   {
   //新建连接到空闲连接池
    int newcount = 0 ;
    //取得要建立的数目
    if (m_instance.MaxConnectionCount - m_instance.current_conn_count >=m_instance.MinConnectionCount)
    {
     newcount = m_instance.MinConnectionCount;
    }
    else
    {
     newcount = m_instance.MaxConnectionCount - m_instance.current_conn_count;
    }
    //创建连接
    for (int i=0;i <newcount; i++)
    {
     _Connection _conn = _Connection.getConnection(m_instance, m_instance.connparam);
     m_instance.FreeConnectionPool.add(_conn);
     m_instance.current_conn_count ++;
    }
   }
   else
   {//如果不能新建,检查是否有已经归还的连接
    iter = m_instance.ConnectionPool.iterator();
    while(iter.hasNext()){
     _Connection _conn = (_Connection)iter.next();
     if(!_conn.isFree()){
      conn = _conn.getFreeConnection();
      _conn.setIsFree(false);
      m_instance.ConnectionPool.remove(_conn); 
      m_instance.FreeConnectionPool.add(_conn);   
      break;
     }
    }    
   }
  }//if (FreeConnectionPool.isEmpty())
 //再次检查是否能分配连接
  if(conn == null){
   iter = m_instance.FreeConnectionPool.iterator();
   while(iter.hasNext()){
    _Connection _conn = (_Connection)iter.next();
    if(!_conn.isFree()){
     conn = _conn.getFreeConnection();
     _conn.setIsFree(true);
     m_instance.FreeConnectionPool.remove(_conn); 
     m_instance.ConnectionPool.add(_conn);   
     break;
    }
   }
   if(conn == null)//如果不能则说明无连接可用
    throw new SQLException("没有可用的数据库连接");
  }
  System.out.println("get connection");
  return conn;
 }
 
 /**
  * 关闭该连接池中的所有数据库连接
  * @throws SQLException
  */
 public synchronized void close() throws SQLException
 {
  this.isflag = false;
  SQLException excp = null;
  //关闭空闲池
  Iterator iter = m_instance.FreeConnectionPool.iterator();
  while(iter.hasNext()){
   try{
    ((_Connection)iter.next()).close();
    System.out.println("close connection:free");
    m_instance.current_conn_count --;
   }catch(Exception e){
    if(e instanceof SQLException)
     excp = (SQLException)e;
   }
  }
  //关闭在使用的连接池
  iter = m_instance.ConnectionPool.iterator();
  while(iter.hasNext()){
   try{
    ((_Connection)iter.next()).close();
    System.out.println("close connection:inused");
    m_instance.current_conn_count --;
   }catch(Exception e){
    if(e instanceof SQLException)
     excp = (SQLException)e;
   }
  }  
  if(excp != null)
   throw excp;
 } 
 
 /**
  * 返回是否支持事务
  * @return boolean
  */
 public boolean isSupportTransaction() {
  return m_instance.supportTransaction;
 }  
 /**
  * 连接池调度管理
  *
  */
 public void schedule()
 {
  Connection conn = null;
  //再检查是否能够分配
  Iterator iter = null;
  //检查是否有已经归还的连接
  {
   iter = m_instance.ConnectionPool.iterator();
   while(iter.hasNext()){
    _Connection _conn = (_Connection)iter.next();
    if(!_conn.isFree()){
     conn = _conn.getFreeConnection();
     _conn.setIsFree(false);
     m_instance.ConnectionPool.remove(_conn); 
     m_instance.FreeConnectionPool.add(_conn);   
     break;
    }
   }    
  }
  if (m_instance.current_conn_count < m_instance.MaxConnectionCount)
  {
   //新建连接到空闲连接池
   int newcount = 0 ;
   //取得要建立的数目
   if (m_instance.MaxConnectionCount - m_instance.current_conn_count >=m_instance.MinConnectionCount)
   {
    newcount = m_instance.MinConnectionCount;
   }
   else
   {
    newcount = m_instance.MaxConnectionCount - m_instance.current_conn_count;
   }
   //创建连接
   for (int i=0;i <newcount; i++)
   {
    _Connection _conn = _Connection.getConnection(m_instance, m_instance.connparam);
    m_instance.FreeConnectionPool.add(_conn);
    m_instance.current_conn_count ++;
   }
  }
 }
}

 


ConnectionParam.java

 package scut.ailab.connectionpool;
import java.io.Serializable;
/**
 * @author youyongming
 * 实现数据库连接的参数类
 */
public class ConnectionParam implements Serializable {
 private String driver;    //数据库驱动程序
 private String url;   //数据连接的URL
 private String user;    //数据库用户名
 private String password;   //数据库密码
 
 /**
  * 唯一的构造函数,需要指定连接的四个必要参数
  * @param driver 数据驱动
  * @param url  数据库连接url
  * @param user  用户名
  * @param password 密码
  */
 public ConnectionParam(String driver,String url,String user,String password)
 {
  this.driver = driver;
  this.url = url;
  this.user = user;
  this.password = password;
 }
 public String getDriver() {
  return driver;
 }
 public String getPassword() {
  return password;
 }
 public String getUrl() {
  return url;
 }
 public String getUser() {
  return user;
 }
 public void setDriver(String driver) {
  this.driver = driver;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 public void setUrl(String url) {
  this.url = url;
 }
 public void setUser(String user) {
  this.user = user;
 }
 /**
  * @see java.lang.Object#clone()
  */
 public Object clone(){
  ConnectionParam param = new ConnectionParam(driver,url,user,password);
  return param;
 }
 /**
  * @see java.lang.Object#equals(java.lang.Object)
  */
 public boolean equals(Object obj) {
  if(obj instanceof ConnectionParam){
   ConnectionParam param = (ConnectionParam)obj;
   return ((driver.compareToIgnoreCase(param.getDriver()) == 0)&&
   (url.compareToIgnoreCase(param.getUrl()) == 0)&&
   (user.compareToIgnoreCase(param.getUser()) == 0)&&
   (password.compareToIgnoreCase(param.getPassword()) == 0));
  }
  return false;
 }
}

 


FactoryMangeThread.java

 /*
 * Created on 2003-5-13
 *
 * To change the template for this generated file go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
package scut.ailab.connectionpool;
/**
 * @author youyongming
 *
 */
//连接池调度线程
public class FactoryMangeThread implements Runnable {
 ConnectionFactory cf = null;
 long delay = 1000;
 public FactoryMangeThread(ConnectionFactory obj)
 {
  cf = obj;
 }
 /* (non-Javadoc)
  * @see java.lang.Runnable#run()
  */
 public void run() {
  while(true){
   try{
    Thread.sleep(delay);
   }
   catch(InterruptedException e){}
   System.out.println("eeeee");
   //判断是否已经关闭了工厂,那就退出监听
   if (cf.isCreate())
    cf.schedule();
   else
    System.exit(1);
  }
 }
}

 


FactoryParam.java

 /*
 * Created on 2003-5-13
 *
 * To change the template for this generated file go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
package scut.ailab.connectionpool;
/**
 * @author youyongming
 *
 */
//连接池工厂参数
public class FactoryParam {
 //最大连接数
 private int MaxConnectionCount = 4;
 //最小连接数
 private int MinConnectionCount = 2;
 //回收策略
 private int ManageType = 0;
 
 public FactoryParam() {
 }
 
 /**
  * 构造连接池工厂参数的对象
  * @param max 最大连接数
  * @param min 最小连接数
  * @param type 管理策略
  */
 public FactoryParam(int max, int min, int type)
 {
  this.ManageType = type;
  this.MaxConnectionCount = max;
  this.MinConnectionCount = min;
 }
 
 /**
  * 设置最大的连接数
  * @param value
  */
 public void setMaxConn(int value)
 {
  this.MaxConnectionCount = value;
 }
 /**
  * 获取最大连接数
  * @return
  */
 public int getMaxConn()
 {
  return this.MaxConnectionCount;
 }
 /**
  * 设置最小连接数
  * @param value
  */
 public void setMinConn(int value)
 {
  this.MinConnectionCount = value;
 }
 /**
  * 获取最小连接数
  * @return
  */
 public int getMinConn()
 {
  return this.MinConnectionCount;
 }
 public int getType()
 {
  return this.ManageType;
 }
}

 


testmypool.java
 /*
 * Created on 2003-5-13
 *
 * To change the template for this generated file go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
package scut.ailab.connectionpool;
/**
 * @author youyongming
 *
 */
import java.sql.*;
public class testmypool {
 public void test1()
 {
  String user = "DevTeam";
  String password = "DevTeam";
  String driver = "sun.jdbc.odbc.JdbcOdbcDriver";
  String url = "jdbc:odbc:gfqh2";
  ConnectionParam param = new ConnectionParam(driver,url,user,password);
  ConnectionFactory cf = null;//new ConnectionFactory(param, new FactoryParam());
  try{
   cf = new ConnectionFactory(param,new FactoryParam());
   Connection conn1 = cf.getFreeConnection();
   Connection conn2 = cf.getFreeConnection();
   Connection conn3 = cf.getFreeConnection();
   Statement stmt = conn1.createStatement();
   ResultSet rs = stmt.executeQuery("select * from requests");
   if (rs.next())
   {
    System.out.println("conn1 y");  
   }
   else
   {
    System.out.println("conn1 n");  
   } 
   stmt.close();
   conn1.close();  
   Connection conn4 = cf.getFreeConnection();
   Connection conn5 = cf.getFreeConnection();
   stmt = conn5.createStatement();
   rs = stmt.executeQuery("select * from requests");
   if (rs.next())
   {
    System.out.println("conn5 y");  
   }
   else
   {
    System.out.println("conn5 n");  
   } 
   conn2.close();
   conn3.close();
   conn4.close();
   conn5.close();
   }
  catch(Exception e)
  {
   e.printStackTrace();
  }
  finally{
   try{
    cf.close();
   }
   catch(Exception e)
   {
    e.printStackTrace();
   }
  } 
 }
 public static void main(String[] args) {
  String user = "DevTeam";
  String password = "DevTeam";
  String driver = "sun.jdbc.odbc.JdbcOdbcDriver";
  String url = "jdbc:odbc:gfqh2";
  ConnectionParam param = new ConnectionParam(driver,url,user,password);
  ConnectionFactory cf = null;//new ConnectionFactory(param,new FactoryParam());
  try{
   cf = new ConnectionFactory(param,new FactoryParam());
   ConnectionFactory cf1= new ConnectionFactory(param,new FactoryParam());
   Connection conn1 = null;
   long time = System.currentTimeMillis();
   for (int i=0; i <10;i++)
   {
    conn1 = cf.getFreeConnection();
    Statement stmt = conn1.createStatement();
    ResultSet rs = stmt.executeQuery("select * from requests");
    if (rs.next())
    {
     System.out.println("conn1 y");  
    }
    else
    {
     System.out.println("conn1 n");  
    } 
    conn1.close();  
   }
   System.out.println("pool:" + (System.currentTimeMillis()-time));
   time = System.currentTimeMillis();
   Class.forName(param.getDriver()).newInstance();
   for (int i=0; i <10;i++)
   {
    conn1 = DriverManager.getConnection(param.getUrl(),param.getUser(), param.getPassword());   
    Statement stmt = conn1.createStatement();
    ResultSet rs = stmt.executeQuery("select * from requests");
    if (rs.next())
    {
     System.out.println("conn1 y");  
    }
    else
    {
     System.out.println("conn1 n");  
    } 
    conn1.close();  
   }   
   System.out.println("no pool:" + (System.currentTimeMillis()-time));
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
  finally{
   try{
    cf.close();
   }
   catch(Exception e)
   {
    e.printStackTrace();
   }
  }
 }
}
  • 关于作者:游永明,人工智能实验室在读研究生,爱好Linux和Java的开发,研究方向是时态数据库。希望能和大家进行探讨和交流,chinascutface@hotmail.com
 

分享到:
评论
2 楼 laorer 2012-03-09  
balan326 写道
你好,最近在网上看了你写的数据库连接池,iteye网你的博客,我想问下ConnectionFactory里的close方法是什么时候调用,看你写的测试是用一次就关闭了,我把它用到我的程序中,我是写游戏后台的,如果每次用了就关闭,第二次调用的时候就要报错,但如果不关闭,过不了多久就会报没有空闲连接的错,请问这个要怎么解决啊


这个是好久之前在网上找到的,现在感觉似乎有点问题,应该使用代理类的方法 _Connection.setIsFree()把数据库连接返回去,而不能使用Connection.close()关掉数据库连接
1 楼 balan326 2012-03-09  
你好,最近在网上看了你写的数据库连接池,iteye网你的博客,我想问下ConnectionFactory里的close方法是什么时候调用,看你写的测试是用一次就关闭了,我把它用到我的程序中,我是写游戏后台的,如果每次用了就关闭,第二次调用的时候就要报错,但如果不关闭,过不了多久就会报没有空闲连接的错,请问这个要怎么解决啊

相关推荐

    java数据库连接池实现

    根据给定的信息,本文将详细解释“Java数据库连接池实现”的相关知识点,包括连接池的基本概念、作用以及如何通过示例代码实现一个简单的Java数据库连接池。 ### Java数据库连接池基本概念 数据库连接池(Database...

    Java jdbc数据库连接池总结.doc

    Java JDBC数据库连接池是Java应用程序与数据库交互的重要优化手段,旨在提高数据库访问效率和资源利用率。在传统的JDBC操作中,每次请求都需要建立和关闭数据库连接,这不仅耗时,还可能导致系统资源的过度消耗,...

    浅谈常用Java数据库连接池(小结)

    在 Java 中,可以使用 DBCP、c3p0、druid 等连接池组件来实现数据库连接池。这些组件提供了多种方式来配置连接池,例如使用 API 方式配置、properties 文件配置等。 6. 连接池的优点 使用连接池可以带来以下几个...

    JDBC数据源连接池的配置和使用示例

    - Druid:阿里巴巴开源的数据库连接池,提供了监控和扩展功能,广泛应用于各种Java Web项目。 ### 3. 配置数据源连接池 以HikariCP为例,我们可以通过以下步骤配置数据源: 1. 添加依赖:在`pom.xml`文件中添加...

    泛微e-cology产品应用和维护常见问题-培训课件2014V1(1).pptx

    - 调整数据库连接池的最大连接数设置,通常可以通过配置文件进行调整。 - 监控应用程序的实际使用情况,确保连接池的设置符合实际需求,避免不必要的资源浪费。 ### 小结 通过对泛微e-cology产品的了解及其常见...

    JDBC与Java数据库编程

    #### 小结 通过本章节的学习,我们了解了JDBC的基本概念、体系结构、API及其版本发展情况,同时也学习了如何使用JDBC来进行基础的数据库操作。接下来,我们将在后续章节中深入探讨JDBC的高级应用以及其他相关的主题...

    Spring boot连接oracle数据库JDBC配置步骤

    小结 通过以上步骤,我们成功地使用 Spring Boot 连接了 Oracle 数据库,并实现了基本的数据库操作。记住,在配置 `application.properties` 文件时,需要根据自己的数据库实例和账户信息进行修改。

    详解springboot 使用c3p0数据库连接池的方法

    C3P0 是一个流行的数据库连接池实现,提供了高性能、可靠性和可扩展性。在本文中,我们将详细介绍如何在 Spring Boot 应用程序中使用 C3P0 数据库连接池。 为什么使用 C3P0? 在 Spring Boot 应用程序中,默认使用...

    Java数据库编程宝典4

    4.6 连接池 4.7 分布式事务处理 4.7.1 分布式事务管理 4.7.2 Connection对象 4.8 SQL语句 4.8.1 Statement对象 4.8.2 PreparedStatement语句 4.8.3 CallableStatement 4.9 事务 4.9.1 事务独立性等级 ...

    Java数据库编程宝典3

    4.6 连接池 4.7 分布式事务处理 4.7.1 分布式事务管理 4.7.2 Connection对象 4.8 SQL语句 4.8.1 Statement对象 4.8.2 PreparedStatement语句 4.8.3 CallableStatement 4.9 事务 4.9.1 事务独立性等级 ...

    Spring boot整合连接池实现过程图解

    * DataSource:Spring Boot提供了DataSource接口,用于定义数据库连接池。 * JDBC Template:Spring Boot提供了JDBC Template,用于简化数据库操作。 * 连接池实现:Spring Boot提供了多种连接池实现,包括HiKariCP...

    语言程序设计资料:第8章_数据库编程.ppt

    数据库连接池是一种管理数据库连接的机制,它可以预先创建一定数量的数据库连接,供多个线程复用,避免了频繁创建和销毁连接的开销。常见的数据库连接池有C3P0、DBCP、HikariCP和Apache DBCP2等。使用连接池可以提高...

    Java数据库编程宝典2

    4.6 连接池 4.7 分布式事务处理 4.7.1 分布式事务管理 4.7.2 Connection对象 4.8 SQL语句 4.8.1 Statement对象 4.8.2 PreparedStatement语句 4.8.3 CallableStatement 4.9 事务 4.9.1 事务独立性等级 ...

    Java_JDBC由浅入深

    第十四节 编写一个简单的数据库连接池 74 14.1 为什么要使用数据库连接池 74 14.2 数据库连接池雏形 74 14.2 数据库连接池优化 77 14.2.1 对线程池加锁 77 14.2.2 连接不够用时抛出异常 77 14.3 数据库连接池之代理...

    JDBC与Java数据库编程.pdf

    - **JDBC驱动程序管理器接口**:这部分由`java.sql.DriverManager`类实现,主要负责加载驱动程序和建立数据库连接。 - **JDBC API**:这部分定义了一系列接口和类,如`java.sql.Connection`、`java.sql.Statement`、...

    Java数据库编程宝典1

    4.6 连接池 4.7 分布式事务处理 4.7.1 分布式事务管理 4.7.2 Connection对象 4.8 SQL语句 4.8.1 Statement对象 4.8.2 PreparedStatement语句 4.8.3 CallableStatement 4.9 事务 4.9.1 事务独立性等级 ...

    java连接oracle.txt

    ### Java 连接 Oracle 数据库方法详解 #### 标题:Java 连接 Oracle #### 描述:本文将详细介绍如何使用 Java 连接到 Oracle 数据库,并...此外,为了提高性能和资源利用率,还可以使用连接池技术来管理数据库连接。

    Java_JDBC学习教程 由浅入深.doc

    - Apache DBCP 是一个常用的开源数据库连接池实现。 - 提供了丰富的配置选项和强大的功能。 #### 十四、JDBC 轻量级封装 - 对 JDBC 进行轻量级封装,可以简化数据库操作,提高代码的可读性和可维护性。 - 可以使用...

    关于JDBC数据分页跨数据库小结.rar

    4. 数据库连接管理:合理使用连接池,避免频繁创建和关闭数据库连接,提高系统性能。 5. 注意数据一致性:在并发环境下,分页查询可能会遇到数据不一致的问题,需考虑事务或乐观锁等机制来保证数据的正确性。 总的...

Global site tag (gtag.js) - Google Analytics