论坛首页 入门技术论坛

完整的连接池类

浏览 4556 次
该帖已经被评为新手帖
作者 正文
   发表时间:2007-09-24  

Oracle连接池需要odbc连接包

1。读取配置文件

db.properties

drivers=oracle.jdbc.driver.OracleDriver

r2gdb.url=jdbc:oracle:thin:@192.168.1.16:1521:r2gdb
r2gdb.user=boss2
r2gdb.password=boss2
r2gdb.maxConns=100
r2gdb.minConns=2
r2gdb.logInterval=60000


r2gdb_boss.url=jdbc:oracle:thin:@192.168.1.16:1521:r2gdb
r2gdb_boss.user=billing
r2gdb_boss.password=billing
r2gdb_boss.maxConns=100
r2gdb_boss.minConns=2
r2gdb_boss.logInterval=60000

 

2.连接池类

package com.database;

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;
  private Hashtable pools = new Hashtable();

  /**
   * 返回唯一实例.如果是第一次调用此方法,则创建实例
   *
   * @return DBConnectionManager 唯一实例
   */
  static synchronized public DBConnectionManager getInstance()
  {
    if (instance == null)
    {
        instance = new DBConnectionManager();
    }
    clients++;
    return instance;
  }

  /**
   * 建构函数私有以防止其它对象创建本类实例
   */
  private DBConnectionManager()
  {
    init();
  }

  /**
   * 将连接对象返回给由名字指定的连接池
   *
   * @param name 在属性文件中定义的连接池名字
   * @param con 连接对象
   */
  public void freeConnection(String name, Connection con)
  {
    DBConnectionPool pool = (DBConnectionPool) pools.get(name);
    if (pool != null)
    {
      pool.freeConnection(con);
      //log("连接反池");
    }
  }

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

  /**
   * 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制,
   * 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.
   *
   * @param name 连接池名字
   * @param time 以毫秒计的等待时间
   * @return Connection 可用连接或null
   */
  public Connection getConnection(String name, long time)
  {
    DBConnectionPool pool = (DBConnectionPool) pools.get(name);
    if (pool != null)
    {
      return pool.getConnection(time);
    }
    return null;
  }

  /**
   * 关闭所有连接,撤销驱动程序的注册
   */
  public synchronized void release()
  {
    // 等待直到最后一个客户程序调用
    if (--clients != 0)
    {
      return;
    }

    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());
      }
    }
  }

  /**
   * 根据指定属性创建连接池实例.
   *
      * <poolname></poolname> .url         The JDBC URL for the database
      * <poolname></poolname> .user        A database user (optional)
      * <poolname></poolname> .password    A database user password (if user specified)
      * <poolname></poolname> .maxconn     The maximal number of connections (optional)
      *
   * @param props 连接池属性
   */
  
  private void createPools(Properties props)
  {
    Enumeration propNames = props.propertyNames();
    while (propNames.hasMoreElements())
    {
      String name = (String) propNames.nextElement();
      if (name.endsWith(".url"))
      {
        String poolName = name.substring(0, name.lastIndexOf("."));
        String url = props.getProperty(poolName + ".url");
        if (url == null)
        {
          //log("没有为连接池" + poolName + "指定URL");
          continue;
        }
        String user = props.getProperty(poolName + ".user");
        String password = props.getProperty(poolName + ".password");
        String maxconn = props.getProperty(poolName + ".maxConns", "0");
  String minconn = props.getProperty(poolName + ".minConns", "0");
  //System.out.println(maxconn);
  //System.out.println(minconn);
        int max, min;
  long logInterval =500;
        try
        {
          max = Integer.valueOf(maxconn).intValue();
    min = Integer.valueOf(minconn).intValue();
        }
        catch (NumberFormatException e)
        {
          //log("错误的最大连接数限制: " + maxconn + " .连接池: " + poolName);
    //log("错误的连接数限制: " + minconn + " .连接池: " + poolName);
          max = 0;
    min = 0;
        }
        DBConnectionPool pool =
            new DBConnectionPool(poolName, url, user, password, max, min,logInterval);
        pools.put(poolName, pool);
        //log("成功创建连接池" + poolName);
      }
    }
  }

  /**
   * 读取属性完成初始化
   */
  private void init()
  {
    InputStream is = getClass().getResourceAsStream("db.properties");
    Properties dbProps = new Properties();
    try
    {
      dbProps.load(is);
    }
    catch (Exception e)
    {
      System.err.println("不能读取属性文件. " +
                         "请确保db.properties在CLASSPATH指定的路径中");
      return;
    }
 String path=getClass().getResource("/").getPath();
 String datapath=path+"com/database/DBConnectionManager.log";
 //datapath=datapath.substring(1,datapath.length());
    String logFile = dbProps.getProperty("logfile",datapath);
    try
    {
      log = new PrintWriter(new FileWriter(logFile, true), true);
    }
    catch (IOException e)
    {
      //System.err.println("无法打开日志文件: " + logFile);
      //log = new PrintWriter(System.err);
    }
    loadDrivers(dbProps);
    createPools(dbProps);
  }

  /**
   * 装载和注册所有JDBC驱动程序
   *
   * @param props 属性
   */
  private void loadDrivers(Properties props)
  {
    String driverClasses = props.getProperty("drivers");
    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);
      }
    }
  }

  /**
   * 将文本信息写入日志文件
   */
  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);
  }

  /**
   * 此内部类定义了一个连接池.它能够根据要求创建新连接,直到预定的最
   * 大连接数为止.在返回连接给客户程序之前,它能够验证连接的有效性.
   */
  class DBConnectionPool
  {
 private final int SLEEP_INTERVAL = 10000;
    private int checkedOut;
    private Vector freeConnections = new Vector();
    private int maxConn;
 private int minConn;
    private String name;
    private String password;
    private String URL;
    private String user;
 private long logTimer;
 private long logInterval;
 private long lastUsedTime;
 private Thread poolMonitor;

 /**
 * 创建新的连接池
 *
 * @param name 连接池名字
 * @param URL 数据库的JDBC URL
 * @param user 数据库帐号,或 null
 * @param password 密码,或 null
 * @param maxConn 此连接池允许建立的最大连接数
 * 每个连接池始终保持一定数量的连接.当申请连接时如果连接池中连接数小于定值
 * 则申请新的连接
 * 连接池设置监控线程每个一段时间就扫描池中的连接如果不可用则删除之并记录连接池的状态
 */
    public DBConnectionPool(String name, String URL, String user,
                            String password,
                            int maxConn, int minConn, long logInterval)
    {
      this.name = name;
      this.URL = URL;
      this.user = user;
      this.password = password;
      this.maxConn = maxConn;
   this.minConn = minConn;
   this.logInterval = logInterval;
   for (int i = 0; i    {
     Connection initConn = newConnection();
   freeConnections.addElement(initConn);
   }
    lastUsedTime=System.currentTimeMillis();
    logTimer = System.currentTimeMillis();
    poolMonitor = new Thread (new Runnable()
    {
        public void run()
        {
            monitor();
        }
    }
    );
    poolMonitor.start();
    }   /* end constructor*/

  private void monitor()
   {
       while ( true )
       {
            ///每隔logInterval对连接池清理一次,删除无效连接,后者在很长一段时间没有使用的连接
             if ( (System.currentTimeMillis() - logTimer) > logInterval)
             { 
              Enumeration checkconn = freeConnections.elements();
     while (checkconn.hasMoreElements())
     {
      Connection con = (Connection) checkconn.nextElement();
               try
      {
       if(con == null || con.isClosed() || (System.currentTimeMillis()-lastUsedTime>12000))
       {
        con.close();
        freeConnections.removeElement(con);
        //log("关闭连接池" + name + "中的一个连接");
       }
      }
      catch(SQLException e)
      {
       System.out.println("momitor 出错!");
      }
              }
                 while (freeConnections.size() < minConn)
                 {
      Connection con = newConnection();
      freeConnections.addElement(con);
     }
      logTimer = System.currentTimeMillis();
             }
             try
             {
     Thread.sleep(SLEEP_INTERVAL);
             }
             catch (InterruptedException e)
             {
              System.out.println("监控线程被打断!!");
             }
         }//end while
  }
    /**
     * 将不再使用的连接返回给连接池
     *
     * @param con 客户程序释放的连接
     */
    public synchronized void freeConnection(Connection con)
    {
      // 将指定连接加入到向量末尾
      freeConnections.addElement(con);
  try
  {
    con.close();
  }catch(Exception e){}
      checkedOut--;
      notifyAll();
    }

    /**
     * 从连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接
     * 数限制,则创建新连接.如原来登记为可用的连接不再有效,则从向量删除之,
     * 然后递归调用自己以尝试新的可用连接.
     */
    public synchronized Connection getConnection()
    {
      Connection con = null;
      if (freeConnections.size() > 0)
      {
        // 获取向量中第一个可用连接
        con = (Connection) freeConnections.firstElement();
        freeConnections.removeElementAt(0);
        try
        {
          if (con.isClosed()||con==null||(System.currentTimeMillis()-lastUsedTime>12000))
          {
            //log("从连接池" + name + "删除一个无效连接");
            // 递归调用自己,尝试再次获取可用连接
            con.close();
         con = getConnection();
          }
        }
        catch (SQLException e)
        {
          //log("从连接池" + name + "删除一个无效连接");
          // 递归调用自己,尝试再次获取可用连接
          con = getConnection();
        }
      }
      else if (maxConn == 0 || freeConnections.size() < maxConn)
      {
        con = newConnection();
      }
      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);
        }
        //log("连接池" + name + "创建一个新的连接");
      }
      catch (SQLException e)
      {
        //log(e, "无法创建下列URL的连接: " + URL);
        return null;
      }
      return con;
    }
  }
}

3。连接池管理类 

package com.database;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class DBConn {

 private Connection conn = null;

 private Statement stmt = null;

 private PreparedStatement prepstmt = null;

 private DBConnectionManager dcm = null;

 private ResultSet rs = null;

 private String connName = null;

 // 初始化
 void init() {
  dcm = DBConnectionManager.getInstance();
  conn = dcm.getConnection(connName);
  while (conn == null) {
   conn = dcm.getConnection(connName, 10);
  }
 }

 // 设置连接
 public void setConnName(String connName) throws Exception {
  this.connName = connName;
  init();
  stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
    ResultSet.CONCUR_UPDATABLE);
 }

 // 构造数据库的连接和访问类
 public DBConn() throws Exception {
  // init();
  // stmt = conn.createStatement();
 }

 /*
  * public DBconn(String connName) throws Exception { this.connName =
  * connName; init(); stmt = conn.createStatement(); }
  */

 public DBConn(int resultSetType, int resultSetConcurrency) throws Exception {
  init();
  stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
    ResultSet.CONCUR_UPDATABLE);
 }

 /**
  * 构造数据库的连接和访问类 预编译SQL语句
  *
  * @param sql
  *            SQL语句
  */
 public DBConn(String sql) throws Exception {
  init();
  this.prepareStatement(sql);
 }

 public DBConn(String sql, int resultSetType, int resultSetConcurrency)
   throws Exception {
  init();
  this.prepareStatement(sql, resultSetType, resultSetConcurrency);
 }

 /**
  * 返回连接
  */
 public Connection getConnection() {
  return conn;
 }

 /**
  * 返回预设状态
  */
 public PreparedStatement getPreparedStatement() {
  return prepstmt;
 }

 /**
  * 返回状态
  */
 public Statement getStatement() {
  return stmt;
 }

 /**
  * 预设SQL语句
  */
 public void prepareStatement(String sql) throws SQLException {
  prepstmt = conn.prepareStatement(sql);
 }

 public void prepareStatement(String sql, int resultSetType,
   int resultSetConcurrency) throws SQLException {
  prepstmt = conn.prepareStatement(sql, resultSetType,
    resultSetConcurrency);
 }

 // *中文转码操作
 public String codingStr(String str) {
  try {
   byte[] temp = str.getBytes("GBK");
   str = new String(temp, "iso8859_1");
  } catch (Exception e) {
   System.out.println(e);
  }
  return str;
 }

 public String to_GBK(String str) {
  try {
   byte[] temp = str.getBytes("iso8859_1");
   str = new String(temp, "GBK");
  } catch (Exception e) {
   System.out.println(e);
  }
  return str;
 }

 /**
  * 设置对应值
  *
  * @param index
  *            参数索引
  * @param value
  *            对应值
  */
 public void setString(int index, String value) throws SQLException {
  prepstmt.setString(index, value);
 }

 public void setInt(int index, int value) throws SQLException {
  prepstmt.setInt(index, value);
 }

 public void setBoolean(int index, boolean value) throws SQLException {
  prepstmt.setBoolean(index, value);
 }

 public void setDate(int index, Date value) throws SQLException {
  prepstmt.setDate(index, value);
 }

 public void setLong(int index, long value) throws SQLException {
  prepstmt.setLong(index, value);
 }

 public void setFloat(int index, float value) throws SQLException {
  prepstmt.setFloat(index, value);
 }

 public void setBytes(int index, byte[] value) throws SQLException {
  prepstmt.setBytes(index, value);
 }

 public void clearParameters() throws SQLException {
  prepstmt.clearParameters();
  prepstmt = null;
 }

 public void commit() throws SQLException {
  conn.commit();
 }

 public void rollback() throws SQLException {
  conn.rollback(); // 操作不成功则回滚
 }

 public void setAutoCommit(boolean str) throws SQLException {
  conn.setAutoCommit(str);
 }

 /**
  * 执行SQL语句返回字段集(用于查找)
  *
  * @param sql
  *            SQL语句
  * @return ResultSet 字段集
  */
 public ResultSet executeQuery(String sql) throws SQLException {
  if (stmt != null) {
   return stmt.executeQuery(sql);
  } else {
   return null;
  }
 }

 public ResultSet executeQuery() throws SQLException {
  if (prepstmt != null) {
   return prepstmt.executeQuery();
  } else {
   return null;
  }
 }

 /**
  * 执行SQL语句(用于更新、插入、删除)
  *
  * @param sql
  *            SQL语句
  */
 public void executeUpdate(String sql) throws SQLException {
  if (stmt != null) {
   stmt.executeUpdate(sql);
  }
 }

 public void executeUpdate() throws SQLException {
  if (prepstmt != null) {
   prepstmt.executeUpdate();
  }
 }

 public CallableStatement prepareCall(String sqlStmt) throws SQLException {
  return conn.prepareCall(sqlStmt);
 }

 /*
  * 执行所有SQL语句
  */
 public int execSQL(String sqlStmt) throws SQLException {
  if (conn == null) {
   init();
  }
  if (stmt == null) {
   stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
     ResultSet.CONCUR_UPDATABLE);
  }
  if (sqlStmt.toUpperCase().startsWith("SELECT")) {
   rs = stmt.executeQuery(sqlStmt);
   return -1;
  } else {
   conn.setAutoCommit(true);
   int numRow = stmt.executeUpdate(sqlStmt);
   return numRow;
  }
 }

 public int execSQL_file(String sqlStmt) throws SQLException {
  if (conn == null) {
   init();
  }
  if (stmt == null) {
   stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
     ResultSet.CONCUR_UPDATABLE);
  }
  if (sqlStmt.toUpperCase().startsWith("SELECT")) {
   rs = stmt.executeQuery(sqlStmt);
   return -1;
  } else {
   conn.setAutoCommit(false);
   int numRow = stmt.executeUpdate(sqlStmt);
   return numRow;
  }
 }

 // 使用字段名获取
 public String getString(String fieldName) throws SQLException {
  if (rs.getString(fieldName) == null
    || rs.getString(fieldName).equals("null"))
   return "";
  else
   return rs.getString(fieldName);
 }

 // 使用字段索引获取
 public String getString(int fieldNo) throws SQLException {
  return rs.getString(fieldNo);
 }

 public int getInt(String fieldName) throws SQLException {
  return rs.getInt(fieldName);
 }

 public int getInt(int fieldNo) throws SQLException {
  return rs.getInt(fieldNo);
 }

 public float getFloat(int fieldNo) throws SQLException {
  return rs.getFloat(fieldNo);
 }

 public float getFloat(String fieldName) throws SQLException {
  return rs.getFloat(fieldName);
 }

 public Date getDate(int fieldNo) throws SQLException {
  return rs.getDate(fieldNo);
 }

 public Date getDate(String fieldName) throws SQLException {
  return rs.getDate(fieldName);
 }

 // 指向第一条的前端(初始位置)
 public void beforeFirst() throws SQLException {
  rs.beforeFirst();
 }

 // 返回是否指向第一条的前端(初始位置)
 public boolean isBeforeFirst() throws SQLException {
  return rs.isBeforeFirst();
 }

 // 指向第一条记录
 public boolean first() throws SQLException {
  return rs.first();
 }

 // 返回是否第一条记录
 public boolean isFirst() throws SQLException {
  return rs.isFirst();
 }

 // 向前移动一条
 public boolean previous() throws SQLException {
  if (rs == null) {
   throw new SQLException("Resultset is null!");
  }
  return rs.previous();
 }

 // 指向下一条记录
 public boolean next() throws SQLException {
  return rs.next();
 }

 // 返回是否存在下一条记录
 public boolean hasNext(String sql) throws SQLException {
  boolean isnext = false;
  execSQL(sql);
  if (rs.next()) {
   isnext = true;
  }
  return isnext;
 }

 // 指向最后一条记录
 public boolean last() throws SQLException {
  return rs.last();
 }

 // 返回是否指向最后一条记录
 public boolean isLast() throws SQLException {
  return rs.isLast();
 }

 // 指向指定的第row行记录
 public boolean absolute(int Row) throws SQLException {
  return rs.absolute(Row);
 }

 // 指向最后一条的下一条记录
 public void afterLast() throws SQLException {
  rs.afterLast();
 }

 // 返回是否指向最后一条记录的下一条记录
 public boolean isAfterLast() throws SQLException {
  return rs.isAfterLast();
 }

 /** ****** relative ******* */
 public boolean relative(int row) throws SQLException {
  return rs.relative(row);
 }

 // 返回指向的记录是第几条
 public int getRow() throws SQLException {
  return rs.getRow();
 }

 // 返回一共有多少条记录
 public int getRows() throws SQLException {
  rs.last();
  int rows = rs.getRow();
  rs.beforeFirst();
  return rows;
 }

 /**
  * 关闭连接
  */
 public void close() throws Exception {
  if (stmt != null) {
   stmt.close();
   stmt = null;
  }
  if (prepstmt != null) {
   prepstmt.close();
   prepstmt = null;
  }
  if (conn != null) {
   dcm.freeConnection(connName, conn);
  }

 }

 /*测试
  * public static void main(String[] args) throws Exception { DBConn dbConn =
  * new DBConn(); dbConn.setConnName("backup"); System.out.println("dd"); }
  */
}


 
   发表时间:2007-09-25  
那个好像不叫内部类哦~!
:)
0 请登录后投票
   发表时间:2008-08-18  
循环是不是没有写完?
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics