jdbc 數據庫連接池

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

          /**
           * 管理類DBHelp支持對一個或多個由屬性文件定義的數據庫連接
           * 池的訪問.客戶程序可以調用getInstance()方法訪問本類的唯一實例.
           
          */


          public class DBHelp {
            
          static private DBHelp instance; // 唯一實例
            static private int clients;

            
          private Vector drivers = new Vector();
            
          private PrintWriter log;
            
          private Hashtable pools = new Hashtable();

            
          /**
             * 返回唯一實例.如果是第一次調用此方法,則創建實例
             *
             * 
          @return DBHelp 唯一實例
             *
          */

            
          static synchronized public DBHelp getInstance() {
              
          if (instance == null{
                instance 
          = new DBHelp();
              }

              clients
          ++;
              
          return instance;
            }


            
          /**
             * 建構函數私有以防止其它對象創建本類實例
             
          */

            
          private DBHelp() {
              init();
            }


            
          /**
             * 將連接對象返回給由名字指定的連接池
             *
             * 
          @param name 在屬性文件中定義的連接池名字
             * 
          @param con 連接對象
             *
          */

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


            
          /**
             * 獲得一個可用連接.若沒有可用連接,且已有連接數小于最大連接數限制,
             * 則創建并返回新連接.否則,在指定的時間內等待其它線程釋放連接.
             *
             * 
          @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());
                }

              }

            }


            
          /**
             * 根據指定屬性創建連接池實例.
             *
             * 
          @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 + ".maxconn""0");
                  
          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);
                }

              }

            }


            
          /**
             * 讀取屬性完成初始化
             
          */

            
          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 logFile 
          = dbProps.getProperty("logfile""DBHelp.log");
              
          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 int checkedOut;
              
          private Vector freeConnections = new Vector();
              
          private int maxConn;
              
          private String name;
              
          private String password;
              
          private String URL;
              
          private String user;

              
          /**
               * 創建新的連接池
               *
               * 
          @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) {
                
          this.name = name;
                
          this.URL = URL;
                
          this.user = user;
                
          this.password = password;
                
          this.maxConn = maxConn;
              }


              
          /**
               * 將不再使用的連接返回給連接池
               *
               * 
          @param con 客戶程序釋放的連接
               
          */

              
          public synchronized void freeConnection(Connection con) {
          // 將指定連接加入到向量末尾
                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();
                }

                
          if (con != null{
                  checkedOut
          ++;
                }

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

                 
          catch (Exception e) {
                   log(
          "無法取得新連接");
                 }

               
          return con;
               }

            }

          }


          posted on 2007-08-15 20:49 hugh 閱讀(319) 評論(0)  編輯  收藏 所屬分類: JAVA

          <2007年8月>
          2930311234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          導航

          統計

          公告

          小弟打算把硬盤里的所有資料整理到博客里,但是其中收藏了不少網上的文章(個人也記不住作者),請作者見諒!請知道作者的朋友(或作者本人)看到了請告訴小弟,小弟好把作者加上!

          常用鏈接

          留言簿(2)

          隨筆分類

          隨筆檔案

          收藏夾

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 元阳县| 磐安县| 万年县| 晋宁县| 东方市| 黎城县| 同德县| 郴州市| 论坛| 昌吉市| 富阳市| 凤冈县| 福贡县| 新河县| 万载县| 永仁县| 井研县| 大悟县| 嘉祥县| 若尔盖县| 高州市| 华蓥市| 通州市| 宜昌市| 临邑县| 枞阳县| 公主岭市| 阿荣旗| 广州市| 凤台县| 福泉市| 六盘水市| 班戈县| 扶沟县| 辛集市| 平谷区| 泰顺县| 全州县| 盐城市| 高邮市| 封丘县|