科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Java基础:一种实现数据库连接池的方法2

Java基础:一种实现数据库连接池的方法2

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

* 连接池类厂,该类常用来保存多个数据源名称合数据库连接池对应的哈希 //由于类属性conn是没有被接管的连接,因此一旦调用close方法后就直接关闭连接  

作者:执木 来源:IT专家网 2008年5月9日

关键字: 方法 连接池 数据库 java

  • 评论
  • 分享微博
  • 分享邮件

* 将指定的名字和数据库连接配置绑定在一起并初始化数据库连接池 

* @param name 对应连接池的名称
  * @param param 连接池的配置参数,具体请见类ConnectionParam
  * @return DataSource 如果绑定成功后返回连接池对象
  * @throws NameAlreadyBoundException 一定名字name已经绑定则抛出该异常
  * @throws ClassNotFoundException 无法找到连接池的配置中的驱动程序类
  * @throws IllegalAccessException 连接池配置中的驱动程序类有误
  * @throws InstantiationException 无法实例化驱动程序类
  * @throws SQLException 无法正常连接指定的数据库
  */
  public static DataSource bind(String name, ConnectionParam param)
  throws NameAlreadyBoundException,ClassNotFoundException,
  IllegalAccessException,InstantiationException,SQLException
  {
  DataSourceImpl source = null;
  try{
  lookup(name);
  throw new NameAlreadyBoundException(name);
  }catch(NameNotFoundException e){
  source = new DataSourceImpl(param);
  source.initConnection();
  connectionPools.put(name, source);
  }
  return source;
  }
  /**
  * 重新绑定数据库连接池
  * @param name 对应连接池的名称
  * @param param 连接池的配置参数,具体请见类ConnectionParam
  * @return DataSource 如果绑定成功后返回连接池对象
  * @throws NameAlreadyBoundException 一定名字name已经绑定则抛出该异常
  * @throws ClassNotFoundException 无法找到连接池的配置中的驱动程序类
  * @throws IllegalAccessException 连接池配置中的驱动程序类有误
  * @throws InstantiationException 无法实例化驱动程序类
  * @throws SQLException 无法正常连接指定的数据库
  */
  public static DataSource rebind(String name, ConnectionParam param)
  throws NameAlreadyBoundException,ClassNotFoundException,
  IllegalAccessException,InstantiationException,SQLException
  {
  try{
  unbind(name);
  }catch(Exception e){}
  return bind(name, param);
  }
  /**
  * 删除一个数据库连接池对象
  * @param name
  * @throws NameNotFoundException
  */
  public static void unbind(String name) throws NameNotFoundException
  {
  DataSource dataSource = lookup(name);
  if(dataSource instanceof DataSourceImpl){
  DataSourceImpl dsi = (DataSourceImpl)dataSource;
  try{
  dsi.stop();
  dsi.close();
  }catch(Exception e){
  }finally{
  dsi = null;
  }
  }
  connectionPools.remove(name);
  }
  }

ConnectionFactory主要提供了用户将将连接池绑定到一个具体的名称上以及取消绑定的操作。使用者只需要关心这两个类即可使用数据库连接池的功能。下面我们给出一段如何使用连接池的代码:
  String name = "pool";
  String driver = " sun.jdbc.odbc.JdbcOdbcDriver ";
  String url = "jdbc:odbc:datasource";
  ConnectionParam param = new ConnectionParam(driver,url,null,null);
  param.setMinConnection(1);
  param.setMaxConnection(5);
  param.setTimeoutValue(20000);
  ConnectionFactory.bind(name, param);
  System.out.println("bind datasource ok.");
  //以上代码是用来登记一个连接池对象,该操作可以在程序初始化只做一次即可
  //以下开始就是使用者真正需要写的代码
  DataSource ds = ConnectionFactory.lookup(name);
  try{
  for(int i=0;i<10;i++){
  Connection conn = ds.getConnection();
  try{
  testSQL(conn, sql);
  }finally{
  try{
  conn.close();
  }catch(Exception e){}
  }
  }
  }catch(Exception e){
  e.printStackTrace();
  }finally{
  ConnectionFactory.unbind(name);
  System.out.println("unbind datasource ok.");
  System.exit(0);
  }
  从使用者的示例代码就可以看出,我们已经解决了常规连接池产生的两个问题。但是我们最最关心的是如何解决接管close方法的办法。接管工作主要在ConnectionFactory中的两句代码:
  source = new DataSourceImpl(param);
  source.initConnection();
  DataSourceImpl是一个实现了接口javax.sql.DataSource的类,该类维护着一个连接池的对象。由于该类是一个受保护的类,因此它暴露给使用者的方法只有接口DataSource中定义的方法,其他的所有方法对使用者来说都是不可视的。我们先来关心用户可访问的一个方法getConnection
  /**
  * @see javax.sql.DataSource#getConnection(String,String)
  */
  public Connection getConnection(String user, String password) throws SQLException
  {
  //首先从连接池中找出空闲的对象
  Connection conn = getFreeConnection(0);
  if(conn == null){
  //判断是否超过最大连接数,如果超过最大连接数
  //则等待一定时间查看是否有空闲连接,否则抛出异常告诉用户无可用连接
  if(getConnectionCount() >= connParam.getMaxConnection())
  conn = getFreeConnection(connParam.getWaitTime());
  else{//没有超过连接数,重新获取一个数据库的连接
  connParam.setUser(user);
  connParam.setPassword(password);
  Connection conn2 = DriverManager.getConnection(connParam.getUrl(),
  user, password);
  //代理将要返回的连接对象
  _Connection _conn = new _Connection(conn2,true);
  synchronized(conns){
  conns.add(_conn);
  }
  conn = _conn.getConnection();
  }
  }
  return conn;
  }
  /**
  * 从连接池中取一个空闲的连接
  * @param nTimeout 如果该参数值为0则没有连接时只是返回一个null
  * 否则的话等待nTimeout毫秒看是否还有空闲连接,如果没有抛出异常
  * @return Connection
  * @throws SQLException
  */
  protected synchronized Connection getFreeConnection(long nTimeout)
  throws SQLException
  {
  Connection conn = null;
  Iterator iter = conns.iterator();
  while(iter.hasNext()){
  _Connection _conn = (_Connection)iter.next();
  if(!_conn.isInUse()){
  conn = _conn.getConnection();
  _conn.setInUse(true);
  break;
  }
  }
  if(conn == null && nTimeout > 0){
  //等待nTimeout毫秒以便看是否有空闲连接
  try{
  Thread.sleep(nTimeout);
  }catch(Exception e){}
  conn = getFreeConnection(0);
  if(conn == null)
  throw new SQLException("没有可用的数据库连接");
  }
  return conn;
  }

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章