Chinaunix首页 | 论坛 | 博客
  • 博客访问: 155245
  • 博文数量: 29
  • 博客积分: 2115
  • 博客等级: 大尉
  • 技术积分: 211
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-13 17:27
个人简介

ddd

文章分类

全部博文(29)

文章存档

2010年(29)

我的朋友

分类: Mysql/postgreSQL

2010-11-10 15:01:06

DBConnectionManager.java
 
一、说明:
1.       数据库连接池管理类
2.       构造数据库连接池
3.       取得数据库连接
4.       释放数据库连接
 
二、变量:
序号
变量名
应用范围
变量类型
初始值
是否static
作用
1
instance
protected
DBConnectionManager
 
连接池管理类实例
2
clients
private
Int
 
记录实例数量
3
dirvers
private
Vector
 
数据库驱动集, 存放多个数据库驱动
4
log
Private
PrintWriter
 
控件日志输出类实例
5
pools
Public
Hashtable
 
连接池集, 存放多个连接池
三、方法简介:
序号
方法名
参数
返回值
功能
1
getInstance
void
返回连接池管理类的实例(static synchronized public)
2
init
Void
实现日志输出, 加载数据库驱动, 创建连接池
3
log
String msg
Void
输出当前日期与日志内容到日志文件
4
log
Throwable e String msg
Void
输出当前日期与日志内容与错误信息到日志文件
5
loadDriver
Void
*从配置文件Configuration类中读取数据库驱动字符串
*各驱动以分隔符分隔, 解析后将其注册到DriverManager 中
*将每个驱动作为元素存入drivers 中
6
createPools
Void
构造内部类数据库连接池DBConnectionPool, 创建连接池实例
将创建的连接池, 存入pools 连接池集中, 每个连接池都有名字
new DBConnectionPool(poolName, url, user, password, max);
7
getCurConns
String poolName
Int
*通过参数poolName 连接池名, 得到连接池实例
*通过连接池实例, 返回一个连接池中当前连接数
*当连接池中所有连接, 被释放之后, 此数值为0
调用 pool.getCurConns();
8
getSumConns
String poolName
int
*通过参数poolName 连接池名, 得到连接池实例
*通过连接池实例, 返回一个连接池中累计连接数
*无论连接是否被释放, 只要使用了连接, 此值是递增的
调用 pool.getSumConns();
9
GetOracleErr
String poolName
int
调用 pool.getOracleErr();
取得连接时有可能到ORACLE 执行错误代码, 没有问题时返回0
10
freeConnection
String poolName
Connection conn
Void
调用pool.freeConnection(con);
释放指定连接池的中的指定连接
11
getNullPool
String poolName
int
调用pool.getNullPool();
得到池空未连接数
12
getMaxConns
String poolName
int
调用 pool.getMaxConns();
*当前的最大连接数
*这个连接数要小于在配置文件中设定的限制连接数
13
getConnection
String poolName
Connection
*获得一个可用的(空闲的)连接.
*如果没有可用连接,且已有连接数小于最大连接数限制,则创建并返回新连接
调用 return pool.getConnection();
14
DBConnectionManager
Void
构造函数, 调用init() 执行初始
15
release
void
public synchronized
*只有唯一连接池管理类
*取出pools 连接池集中所有连接池
*调用pool.release(); 实例释放
*得到drivers 驱动集中所有驱动
*调用 DriverManager.deregisterDriver(driver);注销驱动
16
 
 
 
 
 
四、方法详解:
1、方法名称--freeConnection
(1)方法实体
       /**
        * 将连接对象返回给由名字指定的连接池
        *
        * @param name 在属性文件中定义的连接池名字
        * @param con 连接对象
        */
       public void freeConnection(String name, Connection con)
       {
              DBConnectionPool pool = (DBConnectionPool)pools.get(name);
              if(pool != null)
              {
                     pool.freeConnection(con);
              }
       }
(2)调用实例
DBConnectionManager dbcm = DBConnectionManager.getInstance();
dbcm.freeConnection(“指定的数据库连接池名称”,指定的数据库连接实例);
2、方法名称--getInstance
(1)方法实体
/**
        * 返回唯一实例.如果是第一次调用此方法,则创建实例
        *
        * @return DBConnectionManager 唯一实例
        */
       static synchronized public DBConnectionManager getInstance()
       {
              if(instance == null)
              {
                     instance = new DBConnectionManager();
              }
              clients++;
              return instance;
       }
(2)调用实例
DBConnectionManager dbcm = DBConnectionManager.getInstance();
 
 3、方法名称--getConnection
(1)方法实体
/**
        * 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数
        * 限制,则创建并返回新连接
        *
        * @param name 在属性文件中定义的连接池名字
        * @return Connection 可用连接或null
        */
       public Connection getConnection(String name)
       {
              DBConnectionPool pool = (DBConnectionPool)pools.get(name);
              if(pool != null)
              {
                     return pool.getConnection();
              }
              return null;
       }
(2)调用实例
DBConnectionManager dbcm = DBConnectionManager.getInstance();
Connection conn = dbcm.getConnection(“指定数据库连接池名称”);
 
 
  
DBConnectionPool.java
 
一、说明:
1.此内部类定义了一个连接池。
2.它能够根据要求创建新连接,直到预定的最大连接数为止。
3.在返回连接给客户程序之前,它能够验证连接的有效性.
变量:
序号
变量名
应用范围
变量类型
初始值
是否static
作用
1
sum
private
int
 
 
2
checkedOut
private
int
 
正在使用的连接
3
freeConnections
protected
Vector
 
 
4
maxConn
Private
int
 
 
5
max
Public
Int
 
此连接池允许建立的最大连接数
6
name
 
String
 
连接池名称
7
password
 
String
 
数据库密码
8
URL
 
String
 
数据库连接URL
9
user
 
String
 
数据库用户
10
isNullPool
 
int
 
 
11
isOracleErr
 
int
 
 
12
 
 
 
 
 
 
13
 
 
 
 
 
 
 
二、方法简介:
 
序号
方法名
参数
返回值
功能
1
DBConnectionPool
String name String URL
String user
String password
int maxConn
void
构造函数, 初始化类变量
2
freeConnection
Connection con
Void
public synchronized
*将指定的连接, 存入类Vector变量freeConnections中, 加入到向量的末尾
*正在使用的连接数减1
3
getConnection
void
public synchronized
* 从空闲连接池freeConnections中获得一个可用连接.
* 如没有空闲的连接且当前连接数小于最大连接数限制,则创建新连接.
* 如原来登记为可用的连接不再有效,则从向量删除之, 然后递归调用自己以尝试新的可用连接.
4
getConnection
long timeout
Connection
public synchronized
l        从连接池获取可用连接.
l        可以指定客户程序能够等待的最长时间
l        参见前一个getConnection()方法.
5
release
void
public synchronized
关闭空闲连接池freeConnections中的所有连接
6
newConnection
Connection
Private
创建一个新的连接, 连接数加1(即用getMaxConns返回的值)
7
getCurConns
int
得到当前连接数, 非空闲的
8
getSumConns
int
得到程序调用连接的总次数, 一个连接有可能调用多次
9
getMaxConns
int
得到总的连接数, 空闲+非空闲
10
getNullPool
int
*得到在超出连接数限制后, 继续请求连接的总数
*使用getConnection没有得到连接, 返回null 的个数
11
getOracleErr
int
在使用newConnection 时, 出现异常的次数
12
testConn
Connection conn
int
测试连接是否有效, 执行语句
 

package oa.main;
import  java.io.*;
import  java.sql.*;
import  java.util.*;
import  java.util.Date;

public class DBConnectionManager
{
    /*唯一实例*/
    static private DBConnectionManager instance;
    /*记录实例数量*/
    static private int clients;
    /*数据库驱动集*/
    private Vector drivers = new Vector();
    /*输出日志*/
    private PrintWriter log;
    /*连接池集*/
    public static Hashtable pools = new Hashtable();
   
    /**
     * 返回唯一实例.如果是第一次调用此方法,则创建实例
     *
     * @return DBConnectionManager 唯一实例
     */

    static synchronized public DBConnectionManager getInstance()
    {
        if ( instance == null)
        {
            instance = new DBConnectionManager();
        }
        clients ++;
        return instance;
    }

    /**
      * 构造函数,调用初始化函数,创建连接池管理类
      */  
    private DBConnectionManager()
    {
        init();
    }


    /*
     *  执行初始化
     * 
     * */
    private void init()
    {
        String logFile = Configuration.DB_LOGFILE;
        try {
            log = new PrintWriter(new FileWriter(logFile, true), true);
           
        }catch(IOException e) {
         System.err.println("无法打开日志文件: " + logFile);
         log = new PrintWriter(System.err);
        }
       
        loadDriver();    // 加载数据库驱动
        createPools(); //
    }
    /**
      *  日志输出
      **/
    private void log(String msg)
    {
        log.println(new Date() + ":" + msg);  
    }

    /**
       * 带异常信息的日志输出
       **/
    private void log(Throwable e, String msg)
    {
        log.println(new Date() + ":" + msg);
        e.printStackTrace(log);
    }

    /**
      * 装载数据库连接驱动类,将驱动实例存入数组中
      **/
    private void loadDriver()
    {
        String driverClasses = Configuration.DB_JDBCDRIVER;
        StringTokenizer st = new StringTokenizer(driverClasses);
        while(st.hasMoreElements())
        {
            String driverClassName = st.nextToken().trim();
            try {
                Driver driver = (Driver)Class.forName(driverClassName).newInstance();
                DriverManager.registerDriver(driver);
                drivers.addElement(driver);
                log("成功注册JDBC驱动程序 " + driverClassName);
            }catch (Exception e) {
                log("无法注册JDBC驱动程序 " + driverClassName + "错误: " + e);
                System.out.println("\r\n无法注册JDBC驱动程序: " + driverClassName + "错误: " + e);
            }
        }
    }

    /**
      * 创建数据库连接池,并将其存入连接池数组中
      */
    private void createPools()
    {
        String poolName = Configuration.ConnectionPoolName;
        String url = Configuration.DB_URL;
        if(url == null)
        {
            log("没有为连接池" + poolName + "指定URL");
            return ;
        }
        String user = Configuration.DB_USERNAME;
        String password = Configuration.DB_PASSWORD;
        String maxconn = Configuration.DB_MAXCONNNUM;

        int max;
       
        try {
            max = Integer.valueOf(maxconn).intValue();
        }catch(NumberFormatException e) {
            log("错误的最大连接数限制: " + maxconn + "连接池: " + poolName);
            max = 0;
        }
       
        DBConnectionPool pool = new DBConnectionPool(poolName, url, user, password, max);
        pools.put(poolName, pool);
        log("成功创建连接池" + poolName);
    }


    /*
     *  得到指定连接池中的当前连接数
     *  当连接池中所有连接, 被释放之后, 此数值为0
     *  @return int
     *
     * */

    public static int getCurConns(String name)
    {
        DBConnectionPool pool = (DBConnectionPool)pools.get(name);
        if(pool != null)
        {
            return pool.getCurConns();
        }else  {
            return 0;
        }
    }


    /*
     *  累计连接数
     *  无论连接是否被释放, 只要使用了连接, 此值是递增的
     * **/

    public static int getSumConns(String name)
    {
        DBConnectionPool pool = (DBConnectionPool)pools.get(name);
        if (pool != null)
        {
            return pool.getSumConns();
        }else{
            return 0;
        }
    }


    /*
     *  当前的最大连接数
     *  这个连接数要小于在配置文件中设定的限制连接数
     * **/
    public static int getMaxConns(String name)
    {
        DBConnectionPool pool = (DBConnectionPool)pools.get(name);
        if (pool != null)
        {
            return pool.getMaxConns();
        }else{
            return 0;
        }
    }


    /*
     *  得到池空未连接数
     * * */

    public static int getNullPool(String name)
    {
        DBConnectionPool pool = (DBConnectionPool)pools.get(name);
        if (pool != null)
        {
            return pool.getNullPool();
        }else{
            return 0;
        }
    }

    /*
     *  得到ORACLE 执行错误代码
     *
     * */

    public static int getOracleErr(String name)
    {
        DBConnectionPool pool = (DBConnectionPool)pools.get(name);
        if (pool != null )
        {
            return pool.getOracleErr();
        }else{
            return 0;
        }
    }

    /*
     *  释放指定连接
     * * */

    public void freeConnection(String name, Connection con)
    {
        DBConnectionPool pool = (DBConnectionPool)pools.get(name);
        if (pool != null)
        {
            pool.freeConnection(con);
        }
    }
    /**
     * 获得一个可用的(空闲的)连接.如果没有可用连接
     * 且已有连接数小于最大连接数
     * 限制,则创建并返回新连接
     *
     * @param name 在属性文件中定义的连接池名字
     * @return Connection 可用连接或null
     */

    public Connection getConnection(String name)
    {
        DBConnectionPool pool = (DBConnectionPool)pools.get(name);
        if(pool != null)
        {
            return pool.getConnection();
        }
        return null;
    }
    /*
     *  关闭连接池, 撤销驱动
     *
     * */
    public synchronized void release()
    {
        // 有大于一个连接池管理类的实例时, 返回
        if ( --clients != 0)
        {
            return ;
        }
        else // 只有一个连接池管理类的实例
        {
            Enumeration allPools = pools.elements();
           
            while (allPools.hasMoreElements())
            {
                DBConnectionPool pool = (DBConnectionPool)allPools.nextElement();
                pool.release();
            }
            Enumeration allDrivers = drivers.elements();
            while(allDrivers.hasMoreElements())
            {
                Driver driver = (Driver)allDrivers.nextElement();
                try{
                    DriverManager.deregisterDriver(driver);
                    log("撤销JDBC驱动程序: " + driver.getClass().getName()+"的注册");
                }catch(SQLException e){
                    log(e, "无法撤销下列JDBC驱动程序的注册 " + driver.getClass().getName());
                }
            }
        }
    }
    /**
       * 测试指定连接池的连接情况
       */
    public static void test(String name)
    {
        DBConnectionPool pool =  (DBConnectionPool)pools.get(name);
        pool.test();
    }
/**
     * 从空闲连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接
     * 数限制,则创建新连接.如原来登记为可用的连接不再有效,则从向量删除之,
     * 然后递归调用自己以尝试新的可用连接.
     */


    /**
     * 此内部类定义了一个连接池.它能够根据要求创建新连接,直到预定的最
     * 大连接数为止.在返回连接给客户程序之前,它能够验证连接的有效性.
     */

    class DBConnectionPool
    {
        private int sum;
        private int checkedOut;
        Vector freeConnections = new Vector();
        private int maxConn; // 连接数限制
        private int max;     // 总连接数(空闲+非空闲)
        private String name;
        private String password;
        private String URL;
        private String user;
       
        // 使用getConnection没有得到连接, 返回null 的个数

    public DBConnectionPool(String name ,
                    String URL , String user, String password, int maxConn)
    {   
        this.name    = name;     // 连接池名称
        this.URL      = URL;       // 数据库连接URL
        this.user      = user;       // 数据库用户
        this.password  = password; // 数据库密码
        this.maxConn  = maxConn // 最大连接数
    }
    /**
     * 将不再使用的连接返回给连接池
     *
     * @param con 客户程序释放的连接
     */
    public synchronized void freeConnection(Connection con)
    {
        /**-------------------------------------------------------------------------------------------**/
        // 测试连接的有效性, 可以去掉

        testConn(con);
        /**-------------------------------------------------------------------------------------------**/
        if(con!=null)
        {
            /***------------------------------------------------------------------------------------***/
            // 将指定连接加入到向量末尾
            freeConnections.addElement(con);
            /***------------------------------------------------------------------------------------***/
            // 减少正在使用的连接数量
            checkedOut--;
        }
        /**-------------------------------------------------------------------------------------------**/
        notifyAll();
    }
   
    public synchronized Connection getConnection()
    {
        Connection con = null;
        if(freeConnections.size() > 0)
        {
            // 获取向量中第一个可用连接
            con = (Connection)freeConnections.firstElement();
            freeConnections.removeElementAt(0);
            try{
                if(con.isClosed())
                {
                    log("从连接池" + name + "删除一个无效连接");
                    // 递归调用自己,尝试再次获取可用连接
                    con = getConnection();
                }
            }catch(SQLException e) {
                log("从连接池" + name + "删除一个无效连接");
                // 递归调用自己,尝试再次获取可用连接
                con = getConnection();
            }
        } else if(maxConn == 0 || checkedOut < maxConn){
            con = newConnection();
        } else  { // 大于连接数限制
    System.out.println("  连接池取空,等待回收!");
    isNullPool++ ;
   }
   
   if(con != null)
   {
    checkedOut++;
    sum++;
   }
   
   testConn(con);
   return con;
  }
  /**
   * 从连接池获取可用连接.可以指定客户程序能够等待的最长时间
   * 参见前一个getConnection()方法.
   *
   * @param timeout 以毫秒计的等待时间限制
   */
  public synchronized Connection getConnection(long timeout)
  {
   long startTime = new Date().getTime();
   Connection con;
   while( (con = getConnection()) == null)
   {
    try
    {
     wait(timeout);
    }
    catch(InterruptedException e)
    {}
    if( (new Date().getTime() - startTime) >= timeout)
    {
     // wait()返回的原因是超时
     return null;
    }
   }
   return con;
  }
  /**
   * 关闭所有连接
   */
  public synchronized void release()
  {
   Enumeration allConnections = freeConnections.elements();
   while(allConnections.hasMoreElements())
   {
    Connection con = (Connection)allConnections.nextElement();
    try
    {
     con.close();
     log("关闭连接池" + name + "中的一个连接");
    }
    catch(SQLException e)
    {
     log(e, "无法关闭连接池" + name + "中的连接");
    }
   }
   freeConnections.removeAllElements();
  }
  /**
   * 创建新的连接
   */
  private Connection newConnection()
  {
   Connection con = null;
   try
   {
    if(user == null)
    {
     con = DriverManager.getConnection(URL);
    }
    else
    {
     con = DriverManager.getConnection(URL, user, password);
    }
    /**-------------------------------------------------------------**/
    // 每建一个连接此值都将增加
    max++;
    /**-------------------------------------------------------------**/
    log("连接池" + name + "创建一个新的连接");
   }
   catch(SQLException e)
   {
    //以下注释实在数据库连接调试正常的情况下,因为以下的情况概率最大,所以没有提示连接地址错误
    log(e, "Oracle来不及响应,无法创建下列URL的连接: " + URL);
    //System.out.println("  Oracle来不及响应!");
    isOracleErr ++ ;
    return null;
   }
   return con;
  }
  /*
   *  得到当前连接数非空闲
   * */ 
  public int getCurConns()
  {
   return checkedOut;
  }
  /*
   *  得到程序调用连接的总次数
   *  一个连接可能被调用多次
   * **/
  public int getSumConns()
  {
   return sum ;
  }
  /*
   *  得到总的连接数(空闲+非空闲)
   * ***/ 
  public int getMaxConns()
  {
   return max;
  }
  
  public int getNullPool()
  {
   return isNullPool;
  }
  public int getOracleErr()
  {
   return isOracleErr ;
  }
  public void test()
  {
   System.out.println("\r\n\r\n--------------------vect.size="+freeConnections.size()+"\r\n\r\n");
   for(int i=0;i   {
    Connection conn = (Connection)freeConnections.get(i);
    testConn(conn);
   }
  }
  public void testConn(Connection conn)
  {
   try
   {
    if(conn.isClosed())
    {
       System.out.println("连接池错误:当前连接有问题:该连接破坏!");
    }
    Statement stm = conn.createStatement();
    ResultSet rs = stm.executeQuery("select count(*) from sms");
    
    rs.next();
    rs.close();
    stm.close();
    //System.out.println(i+"="+rs.getInt(1));
   }
   catch(SQLException s){System.out.println("连接池错误:当前连接有问题:"+s);}
  }
 }
}
 
        // 在超出连接数限制后, 继续请求连接时此值增加
        private int isNullPool
        // 数据库错误
        private int isOracleErr;
        
    /**
     * 创建新的连接池
     *
     * @param name 连接池名字
     * @param URL 数据库的JDBC URL
     * @param user 数据库帐号,或 null
     * @param password 密码,或 null
     * @param maxConn 此连接池允许建立的最大连接数
     */
阅读(3002) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~