`

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 jdbc数据库连接池总结

    Java JDBC 数据库连接池总结 Java 语言中,JDBC(Java DataBase Connection)是应用程序与数据库沟通的桥梁。在 Web 应用开发的早期,主要使用的技术是 CGIASPPHP 等。之后,Sun 公司推出了基于 Java 语言的 ...

    java_jdbc数据库连接池总结

    Java JDBC 数据库连接池总结 Java JDBC 数据库连接池是 Java 应用程序访问数据库的基本原理之一。Java 语言通过 JDBC 技术访问数据库,JDBC 是一种“开放”的方案,为数据库应用开发人员和数据库前台工具开发人员...

    JAVA 完整的数据库连接池实现

    Java 数据库连接池是 Java 应用程序中用于管理数据库连接的重要工具,它极大地提高了应用程序的性能和效率。本文将详细介绍如何在 Java 中实现一个完整的数据库连接池,并探讨其核心概念、工作原理以及如何根据需求...

    java手写数据库连接池

    首先,数据库连接池的基本原理是维护一定数量的数据库连接,当应用需要时,可以从池中获取一个已建立的连接,使用完毕后再归还给池,而不是直接关闭。这样避免了频繁地创建和销毁连接,提高了系统的效率。 1. **...

    java数据库连接池

    标题:Java数据库连接池 描述:本篇将详细介绍Java数据库连接池的概念,代码实现以及其在实际项目中的应用。数据库连接池是Java开发中优化数据库访问效率的关键技术,通过复用预创建的数据库连接,避免频繁创建和...

    JAVA数据库连接池

    Java数据库连接池是Java开发中一个非常重要的技术,它主要用于管理数据库连接,提高数据库操作的效率和性能。在Java应用程序中,频繁地创建和关闭数据库连接会导致大量的系统资源浪费,而连接池则可以复用已建立的...

    java写的数据库连接池

    数据库连接池是Java开发中非常重要的一个概念,它在处理大量并发访问数据库的应用场景中扮演着关键角色。本文将深入探讨数据库连接池的工作原理、重要性以及如何在Java中实现一个简单的连接池。 首先,数据库连接池...

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

    Java JDBC 数据库连接池技术是Java应用程序访问数据库的关键优化手段,尤其在Web应用程序中,它解决了传统JDBC连接方式存在的效率低下和资源浪费问题。Java JDBC(Java Database Connectivity)是Java语言与各种...

    java oracle 数据库 连接池 小例子

    数据库连接池在初始化时会创建一定数量的数据库连接,这些连接在应用程序需要时可以被复用,而不是每次请求时都创建新的连接,从而减少了创建和销毁连接的开销。C3P0作为连接池实现之一,提供了很多配置参数,例如...

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

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

    Java数据库连接池的原理与应用.pdf

    Java数据库连接池的原理与应用 在Java开发领域,数据库连接池(Database Connection Pool,简称DBCP)是一种提高数据库访问性能、降低资源消耗的重要技术。它通过预先建立一定数量的数据库连接,存储在一个“池”中...

    自己写的数据库连接池(java)

    数据库连接池是Java应用程序中非常重要的一个组成部分,它在处理多用户并发访问数据库时能显著提高性能和资源利用率。在给定的标题“自己写的数据库连接池(java)”中,我们可以推测这是一个用户自定义的数据库连接池...

    基于Java的数据库连接池设计与优化.pdf

    "基于Java的数据库连接池设计与优化" 本文总结了基于Java的数据库连接池设计与优化技术,讨论了传统数据库开发模式的不足,提出了数据库连接池技术,并对其基本模型和设计方案进行了探讨。在静态连接池的设计基础上...

    数据库连接池 java 整理

    数据库连接池是一种管理数据库连接的机制,它允许程序高效地重复使用已建立的数据库连接,而不是每次需要时都创建新的连接。这显著提高了性能,减少了资源消耗,并降低了数据库服务器的压力。 在Java中,有多种流行...

Global site tag (gtag.js) - Google Analytics