`

Java建立数据库连接池

    博客分类:
  • JDBC
 
阅读更多

 

package mc;

 

import java.util.*;
import java.util.Date;
import java.sql.*;
import java.io.*;

 

public class DBConnectionManager {

 

 /** 日志文件写入流对象 */
 private PrintWriter log;

 

 /** 存放连接池对象Hashtable */
 private Hashtable pools;

 

 /** DBConnectionManager 唯一实例 */
 static private DBConnectionManager instance;

 

 /** 记录客户机的连接数 */
 static private int remotes;

 

 /** 存放数据库连接驱动 */
 private Vector drivers;

 


 /**
  * 类名:     DBConnectionManager<br>
  * 函数功能: 私有构造方法<br>
  * 返回值:   无<br>
  * 参数说明: 无<br>
  * 创建人: andy<br>
  * 创建时间: 2006年9月1日
  * 最后修改: 无<br>
  */
 private DBConnectionManager()
 {
  init();
 }

 

 /**
  * 类名:     DBConnectionManager<br>
  * 函数功能: 初始化类属性<br>
  * 返回值:   无<br>
  * 参数说明: 无<br>
  * 创建人: andy<br>
  * 创建时间: 2006年9月1日
  * 最后修改: 无<br>
  */
 private void init()
 {
  pools = new Hashtable();
  drivers = new Vector();
                //建立属性对象
  Properties prop = new Properties();
                //把属性文件的属性列表读到属性对象
  try {
            InputStream is = getClass().getResourceAsStream("db.properties");
   prop.load(is);
  } catch (IOException e) {
   e.printStackTrace();
   System.out.println("读取属性文件错误!");
  }
  // 建立日志文件输入流对象
  String logFilePath = prop.getProperty("logFile");
  try {
   log = new PrintWriter(new FileWriter(logFilePath,true),true);
  } catch (IOException e) {
   e.printStackTrace();
   System.out.println("无法打开日志文件:" + logFilePath);
   log = new PrintWriter(System.err);
  }
  // 加载和注册数据库驱动
  loadDriver(prop);
  // 初始化和创建连接池实例
  createPools(prop);
 }

 


 /**
  * 类名:     DBConnectionManager<br>
  * 函数功能: 返回 DBConnectionManager 唯一实例.如果是第一次调用此方法,则创建实例<br>
  * 返回值:   DBConnectionManager 对象<br>
  * 参数说明: 无<br>
  * 创建人: andy<br>
  * 创建时间:  2006年9月1日
  * 最后修改: 无<br>
  */
 static synchronized public DBConnectionManager getInstance()
 {
  if(instance == null){
   instance = new DBConnectionManager();
  }
  remotes++;
  return instance;
 }

 

 /**
  * 类名:     DBConnectionManager<br>
  * 函数功能: 把文本信息写入日志文件<br>
  * 返回值:   无<br>
  * 参数说明: String message 信息描述字符串<br>
  * 创建人: andy<br>
  * 创建时间:  2006年9月1日
  * 最后修改: 无<br>
  */
 private void logWriter(String message)
 {
  log.println("日期: " + new Date() + message);
 }

 

 private void logWriter(Throwable e,String errMessage)
 {
  log.println("日期: " + new Date() + errMessage + "\n错误: ");
  e.printStackTrace(log);    // 把异常描述写入日志文件
 }

 

 /**
  * 类名:     DBConnectionManager<br>
  * 函数功能: 获取一个数据库连接<br>
  * 返回值:   Connection类型<br>
  * 参数说明: String poolName 接收连接池名称<br>
  * 创建人: andy<br>
  * 创建时间:  2006年9月1日
  * 最后修改: 无<br>
  */
 public Connection getConnection(String poolName)
 {
  // 通过连接池名称返回连接池对象
  DBConnectionPool pool = (DBConnectionPool) pools.get(poolName);
  if(pool == null){
   logWriter("试图使用不存在的连接池" + poolName);
   return null;
  }
  // 返回连接给用户.
  return pool.getConnection();
 }

 

 /**
  * 类名:     DBConnectionManager<br>
  * 函数功能:  释放连接,把用完的连接归还给连接池<br>
  * 返回值:   无<br>
  * 参数说明: String poolName 连接池名称,Connection conn 连接对象<br>
  * 创建人: andy<br>
  * 创建时间: 2006年9月1日
  * 最后修改: 无<br>
  */
 public void RefeaseConnection(String poolName,Connection conn)
 {
  DBConnectionPool pool = (DBConnectionPool) pools.get(poolName);
  if(pool == null){
   logWriter("释放连错误!请检查连接池名称.");
   return;
  }else{
   pool.freeConnection(conn);
  }
 }

 

        /**
         * 类名:     DBConnectionManager<br>
         * 函数功能:  释放连接,把用完的连接归还给连接池<br>
         * 返回值:   无<br>
         * 参数说明: String poolName 连接池名称,Connection conn 连接对象<br>
         * 创建人: andy<br>
         * 创建时间: 2006年9月1日
         * 最后修改: 无<br>
  */
        public void RefeaseConnection
        (String poolName,Connection conn,Statement stn,PreparedStatement ptn,ResultSet result)
       {
               try {
                   if (stn != null)
                       stn.close();
                   if (ptn != null)
                       ptn.close();
                   if (result != null)
                       result.close();
               }catch(Exception ex)
               {
                   ex.printStackTrace(System.out);
                   System.out.println(ex.getMessage());
               }
               DBConnectionPool pool = (DBConnectionPool) pools.get(poolName);
               if(pool == null){
                       logWriter("释放连错误!请检查连接池名称.");
                       return;
               }else{
                       pool.freeConnection(conn);
               }

 

        }

 

 

 

 /**
  * 类名:     DBConnectionManager<br>
  * 函数功能: 释放所有的连接,注销驱动<br>
  * 返回值:   无<br>
  * 参数说明: 无<br>
  * 创建人: andy<br>
  * 创建时间: 2006年9月1日
  * 最后修改: 无<br>
  */
 public synchronized void releas()
 {
  if(--remotes != 0){
   return;
  }
  Enumeration ePools =  pools.elements();
  while(ePools.hasMoreElements()){
   DBConnectionPool pool = (DBConnectionPool) ePools.nextElement();
   //关闭所有的连接对象
   pool.release();
  }
  Enumeration eDrivers = drivers.elements();
  while(eDrivers.hasMoreElements()){
   Driver driver = (Driver) eDrivers.nextElement();
   try {
    DriverManager.deregisterDriver(driver);
    logWriter("注销" + driver.getClass().getName() + "成功!");
   } catch (SQLException e) {
    logWriter(e,"无法注销" + driver.getClass().getName() + "驱动!");
    e.printStackTrace();
   }
  }
 }

 

 /**
  * 类名:     DBConnectionManager<br>
  * 函数功能: 加载和注册数据库驱动程序<br>
  * 返回值:   无<br>
  * 参数说明: Properties prop变量接收数据库属性列表<br>
  * 创建人: andy<br>
  * 创建时间: 2006年9月1日
  * 最后修改: 无<br>
  */
 private void loadDriver(Properties prop)
 {
  // 从prop属性对象中取出驱动字符串
  String driverClass = prop.getProperty("drivers");
  // 把驱动字符串分解为标记
  StringTokenizer st = new StringTokenizer(driverClass);
  while(st.hasMoreTokens()){
   String driverClassName = st.nextToken().trim();
   try {
    // 加载数据库驱动
    Driver driver = (Driver) Class.forName(driverClassName).newInstance();
    // 注册数据库驱动
    DriverManager.registerDriver(driver);
    drivers.addElement(driver);
    // 把注册相关信息写入日志文件
    logWriter("成功注册数据库驱动.");
   } catch (InstantiationException e) {
    logWriter("加载数据库驱动错误:" + e.getMessage());
    e.printStackTrace();
   } catch (IllegalAccessException e) {
    logWriter("加载数据库驱动错误:" + e.getMessage());
    e.printStackTrace();
   } catch (ClassNotFoundException e) {
    logWriter("加载数据库驱动错误:" + e.getMessage());
    e.printStackTrace();
   } catch (SQLException e) {
    logWriter("无法数据库驱动:" + e.getMessage());
    e.printStackTrace();
   }
  }
 }

 

 /**
  * 类名:     DBConnectionManager<br>
  * 函数功能: 初始化和建立连接池实例<br>
  * 返回值:   无<br>
  * 参数说明: Properties prop 变量接收设置连接池属性列表;如 最大连接数,最少连接数等<br>
  * 创建人: andy<br>
  * 创建时间: 2006年9月1日
  * 最后修改: 无<br>
  */
 private void createPools(Properties prop)
 {
  /** 返回属性列表中所有键的枚举 */
  Enumeration propNames = prop.propertyNames();
  while(propNames.hasMoreElements()){
   String name = (String) propNames.nextElement();
   if(name.endsWith(".url")){
    // propName 以后用做连接池名称
    String poolName = name.substring(0,name.indexOf("."));
    String url = prop.getProperty(poolName + ".url").trim();
    if(poolName == null || url == null){
     log.print("没有连接池:" + poolName + " 指定的URL");
     continue;
    }

 

    String user = prop.getProperty(poolName + ".user").trim();
    String password = prop.getProperty(poolName + ".password").trim();
    String strMaxConn = prop.getProperty(poolName + ".maxConn").trim();
                                String strMinConn = prop.getProperty(poolName + ".minConn").trim();
    int maxConn = 0,minConn = 0;
    try{
     maxConn = Integer.parseInt(strMaxConn);
                                        minConn = Integer.parseInt(strMinConn);
     }catch(NumberFormatException ne){
      maxConn = 100;
                                                minConn = 50;
      logWriter(ne," 属性文件中的最大连接数错误,请检查书写是否正确!" +
        "此错误出现后,系统自动设置最大连接数为100");
     }
    //取得数据库属性文件中的相关设置后开始建立连接池
    DBConnectionPool pool = new DBConnectionPool(poolName,url,user,password,maxConn,minConn);
    //把连接池放到 Hashtable
    pools.put(poolName, pool);
    logWriter("连接池创建成功!");
   }
  }
 }

 

 /**
  * 类名:       DBConnectionPool类是DBConnectionManager类的内部类<br>
  * 内部类功能:  此内部类定义了一个连接池.它能够根据要求创建新连接,直到预定的最大连接数为止.
     在返回连接给客户程序之前,它能够验证连接的有效性.<br>
  * 返回值:    无<br>
  * 参数说明:  <br>
  * 创建人:  andy<br>
  * 创建时间:   2006年9月1日
  * 最后修改:  无<br>
  */
 class DBConnectionPool
 {
  /** 记录分出的连接数 */
  private int checkOut;

 

  /** 存放连接的 Vector 对象 */
  private Vector freeConnection;

 

  /** 数据库帐户 */
  private String user;

 

  /** 登陆密码 */
  private String password;

 

  /** 连接池名称 */
  private String poolName;

 

  /** 数据源URL */
  private String url;

 

  /** 最大连接数 */
  private int maxConn;

 

                /** 最小连接数 */
                private int minConn;

 

  /**
   * 类名:     DBConnectionPool<br>
   * 函数功能: 构造方法<br>
   * 返回值:   无<br>
   * 参数说明: String poolName 接收连接池名称; String url 数据源URL;
       String user 数据库帐户; String password 密码; int maxConn 设置最大的连接数<br>
   * 创建人: andy<br>
   * 创建时间: 2006年9月1日
   * 最后修改: 无<br>
   */
  public DBConnectionPool(String poolName, String url, String user,
    String password, int maxConn,int minConn) {

 

   freeConnection = new Vector();
   this.poolName = poolName;
   this.url = url;
   this.user = user;
   this.password = password;
   this.maxConn = maxConn;
                        this.minConn = minConn;
                        init();
  }

 


                /**
                 * 类名:     DBConnectionPool<br>
                 * 函数功能: 该方法在程序第一次运行时生成最小连接数。<br>
                 * 返回值:   Connection 对象<br>
                 * 参数说明: 无<br>
                 * 创建人: andy<br>
                 * 创建时间: 2006年9月1日
                 * 最后修改: 无<br>
                 */

 

                private void init() {
                     Connection conn = null;
                    for (int i = 0; i < minConn; i++) {
                        try {
                            conn = DriverManager.getConnection(url, user, password);
                            logWriter("连接池: " + poolName + " 创建了一个新连接");
                        } catch (SQLException e) {
                            logWriter(e, "无法建立:" + url + "连接");
                            e.printStackTrace();
                        }
                        freeConnection.addElement(conn);
                    }
                }

 

  /**
   * 类名:     DBConnectionPool<br>
   * 函数功能: 返回连接对象<br>
   * 返回值:   Connection 对象<br>
   * 参数说明: 无<br>
   * 创建人: andy<br>
   * 创建时间: 2006年9月1日
   * 最后修改: 无<br>
   */
  public Connection getConnection(){
   Connection conn = null;

 

   if(freeConnection.size() > 0){
    //当连接池中有空闲的连接,就从池中取出一条连接
    conn = (Connection) freeConnection.firstElement();
    //连接取出后,从连接池中删除该连接的记录.
    freeConnection.removeElementAt(0);
    try {
     //判断所取出的连接是否有效
     if(conn.isClosed()){
      logWriter("从连接池 "+ poolName +" 中删除一条无效的连接");
      //递归调用自己,获取可用的连接
      conn = getConnection();
     }
    } catch (SQLException e) {
     logWriter("从连接池 "+ poolName +" 中删除一条无效的连接");
     e.printStackTrace();
     //递归调用自己,获取可用的连接
     conn = getConnection();
    }
    // 当连接池中没有可用的连接,且当前的连接数在设置最大的连接数以下.新建一个连接
   }else if(checkOut < maxConn){
    conn = newConnection();
    // 当连接池中没有可用的连接,且当前连接已经达到最大连接数.
   }else{
    try {
     Thread.sleep(500);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    //等待500毫秒后,递归调用自己,获取可用的连接
    conn = getConnection();
   }
   // 记录分出去的连接数
   checkOut++;
   return conn;
  }

 

  /**
   * 类名:     DBConnectionPool<br>
   * 函数功能: 返回新建的连接对象<br>
   * 返回值:   Connection 对象<br>
   * 参数说明: 无<br>
   * 创建人: andy<br>
   * 创建时间: 2006年9月1日
   * 最后修改: 无<br>
   */
  public Connection newConnection(){
   Connection conn = null;
   try {
    conn = DriverManager.getConnection(url,user,password);
    logWriter("连接池: " + poolName + " 创建了一个新连接");
   } catch (SQLException e) {
    logWriter(e,"无法建立:" + url + "连接");
    e.printStackTrace();
   }
   return conn;
  }

 

  /**
   * 类名:     DBConnectionPool<br>
   * 函数功能: 释放连接对象<br>
   * 返回值:   无<br>
   * 参数说明: 无<br>
   * 创建人: andy<br>
   * 创建时间: 2006年9月1日
   * 最后修改: 无<br>
   */
  synchronized public void freeConnection(Connection conn)
  {
   // 把连接对象放回 Vector 里
   freeConnection.addElement(conn);
   // 连接数减1
   checkOut--;
   // 唤醒在此对象监视器上等待的所有线程
   notifyAll();
  }

  public synchronized void release()
  {
   Enumeration allConn = freeConnection.elements();
   while(allConn.hasMoreElements()){
    Connection conn = (Connection) allConn.nextElement();
    try {
     conn.close();
     logWriter("成功关闭连接!");
    } catch (SQLException e) {
     logWriter(e,"无法关闭连接池" + poolName + "中连接!");
     e.printStackTrace();
    }
    //清空 Vector 中的所有元素
    freeConnection.removeAllElements();
   }
  }
 }
}

分享到:
评论

相关推荐

    java数据库连接池

    当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。 我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。 更为重要的是我们可以通过连接池的治理机制监视数据库的连接的数量...

    经典的Java数据库连接池程序

    虽然现在用APACHE COMMONS DBCP可以非常方便的建立数据库连接池, 但是像这篇文章把数据库连接池的内部原理写的这么透彻,注视这么完整, 真是非常难得,让开发人员可以更深层次的理解数据库连接池。

    在WebLogic中建立数据库连接池与数据源及利用JBuilder进行测试

    在WebLogic中建立数据库连接池与数据源及利用JBuilder进行测试

    Java_jdbc数据库连接池总结

    预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池...

    数据库连接池(database connection pool)是在 Java 中用于管理数据库连接的一种技术

    数据库连接池(database connection pool)是在 Java 中用于管理数据库连接的一种技术。它的主要目的是提高数据库连接的重用性和性能。在传统的数据库连接方式中,每次与数据库建立连接时都需要进行一系列的网络通信...

    DBCP数据库连接池1.2jar包

    DBCP(DataBase connection pool),数据库连接池。是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。单独使用dbcp需要3个包:commons-dbcp.jar,commons-pool.jar,commons-collections.jar由于建立...

    java-JSP数据库连接池的研究与实现(源代码+论文)

    这种技术类似于CPU 中的Cache 技术,将预先设定好的数据库连接放入该缓冲池中,当要建立数据库连接操作时,便从池中取出一个连接,使用完毕后再将其放回。这样就达到了连接复用的目的,应用程序重复使用一个数据库...

    在WebLogic中建立数据库连接池与数据源及利用JBuilder进行测试.pdf

    在WebLogic中建立数据库连接池与数据源及利用JBuilder进行测试.pdf

    用apache的dbcp来建立数据库连接池

    用apache的dbcp来建立数据库连接池

    常用开源数据库连接池 文档和源码及jar包

    单独使用dbcp需要3个包:common-dbcp.jar,common-pool.jar,common-collections.jar由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库...

    Kettle简单参数化配置连接数据库

    参数化配置数据库连接,以及简单shell如何传参调度Kettle

    c3p0数据库连接池案例

    c3p0数据库连接池案例,java项目,例子结构清晰,适合新手学习

    Java_jdbc数据库连接池总结.doc

     程序开发,存在很多问题:首先,每一次Web请求都要建立一次数据库连接。建立连接是一个费时的活动,每次都得花费0.05s~1s的时间,而且系统还要分配内存资源。这个时间对于一次或几次数据库操作,或许感觉不出系统...

    数据源和连接池

    在实际项目的开发中,特别是web应用程序中,如Jsp,Servlet或EJB使用JDBC直接访问数据库中的...使用数据库连接池技术是解决上述问题的最常用的方法,在许多应用服务器(如 websphere, weblogic ,jBoss)中都提供了这种技术

    Spring Boot与HikariCP:性能卓越的数据库连接池

    本文将详细介绍Spring Boot中如何使用HikariCP作为数据库连接池,包括其工作原理、优势分析、配置步骤以及代码示例。通过本文,读者将能够轻松集成HikariCP到Spring Boot项目中,从而提高数据库连接的性能和效率。 ...

    c3p0-0.9.5.2的三个jar包 数据库连接池

    用来在java连接数据库时候,c3p0建立相应的数据连接池

    Java中常用的数据库连接池_动力节点Java学院整理

    数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏

    DBCP连接池所需完整架包(全)

    DBCP(DataBase connection pool),数据库连接池。是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。单独使用dbcp需要2个包:commons-dbcp.jar,commons-pool.jar由于建立数据库连接是一个非常耗时耗...

    数据库连接池jar包.zip

    适合初学者快速导入建立jbdc链接

Global site tag (gtag.js) - Google Analytics