jdbc 數(shù)據(jù)庫連接池

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

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


          public class DBHelp {
            
          static private DBHelp instance; // 唯一實(shí)例
            static private int clients;

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

            
          /**
             * 返回唯一實(shí)例.如果是第一次調(diào)用此方法,則創(chuàng)建實(shí)例
             *
             * 
          @return DBHelp 唯一實(shí)例
             *
          */

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

              clients
          ++;
              
          return instance;
            }


            
          /**
             * 建構(gòu)函數(shù)私有以防止其它對象創(chuàng)建本類實(shí)例
             
          */

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

            }


            
          /**
             * 獲得一個(gè)可用的(空閑的)連接.如果沒有可用連接,且已有連接數(shù)小于最大連接數(shù)
             * 限制,則創(chuàng)建并返回新連接
             *
             * 
          @param name 在屬性文件中定義的連接池名字
             * 
          @return Connection 可用連接或null
             
          */

            
          public Connection getConnection(String name) {
              DBConnectionPool pool 
          = (DBConnectionPool) pools.get(name);
              
          if (pool != null{
                
          return pool.getConnection();
              }

              
          return null;
            }


            
          /**
             * 獲得一個(gè)可用連接.若沒有可用連接,且已有連接數(shù)小于最大連接數(shù)限制,
             * 則創(chuàng)建并返回新連接.否則,在指定的時(shí)間內(nèi)等待其它線程釋放連接.
             *
             * 
          @param name 連接池名字
             * 
          @param time 以毫秒計(jì)的等待時(shí)間
             * 
          @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;
            }


            
          /**
             * 關(guān)閉所有連接,撤銷驅(qū)動(dòng)程序的注冊
             
          */

            
          public synchronized void release() {
          // 等待直到最后一個(gè)客戶程序調(diào)用
              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驅(qū)動(dòng)程序 " + driver.getClass().getName() + "的注冊");
                }

                
          catch (SQLException e) {
                  log(e, 
          "無法撤銷下列JDBC驅(qū)動(dòng)程序的注冊: " + driver.getClass().getName());
                }

              }

            }


            
          /**
             * 根據(jù)指定屬性創(chuàng)建連接池實(shí)例.
             *
             * 
          @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(
          "錯(cuò)誤的最大連接數(shù)限制: " + maxconn + " .連接池: " + poolName);
                    max 
          = 0;
                  }

                  DBConnectionPool pool 
          =
                      
          new DBConnectionPool(poolName, url, user, password, max);
                  pools.put(poolName, pool);
                  log(
          "成功創(chuàng)建連接池" + 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驅(qū)動(dòng)程序
             *
             * 
          @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驅(qū)動(dòng)程序" + driverClassName);
                }

                
          catch (Exception e) {
                  log(
          "無法注冊JDBC驅(qū)動(dòng)程序: " +
                      driverClassName 
          + ", 錯(cuò)誤: " + 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);
            }


            
          /**
             * 此內(nèi)部類定義了一個(gè)連接池.它能夠根據(jù)要求創(chuàng)建新連接,直到預(yù)定的最
             * 大連接數(shù)為止.在返回連接給客戶程序之前,它能夠驗(yàn)證連接的有效性.
             
          */

            
          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;

              
          /**
               * 創(chuàng)建新的連接池
               *
               * 
          @param name 連接池名字
               * 
          @param URL 數(shù)據(jù)庫的JDBC URL
               * 
          @param user 數(shù)據(jù)庫帳號,或 null
               * 
          @param password 密碼,或 null
               * 
          @param maxConn 此連接池允許建立的最大連接數(shù)
               
          */

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


              
          /**
               * 從連接池獲得一個(gè)可用連接.如沒有空閑的連接且當(dāng)前連接數(shù)小于最大連接
               * 數(shù)限制,則創(chuàng)建新連接.如原來登記為可用的連接不再有效,則從向量刪除之,
               * 然后遞歸調(diào)用自己以嘗試新的可用連接.
               
          */

              
          public synchronized Connection getConnection() {
                Connection con 
          = null;
                
          if (freeConnections.size() > 0{
          // 獲取向量中第一個(gè)可用連接
                  con = (Connection) freeConnections.firstElement();
                  freeConnections.removeElementAt(
          0);
                  
          try {
                    
          if (con.isClosed()) {
                      log(
          "從連接池" + name + "刪除一個(gè)無效連接");
          // 遞歸調(diào)用自己,嘗試再次獲取可用連接
                      con = getConnection();
                    }

                  }

                  
          catch (SQLException e) {
                    log(
          "從連接池" + name + "刪除一個(gè)無效連接");
          // 遞歸調(diào)用自己,嘗試再次獲取可用連接
                    con = getConnection();
                  }

                }

                
          else if (maxConn == 0 || checkedOut < maxConn) {
                  con 
          = newConnection();
                }

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

                
          return con;
              }


              
          /**
               * 從連接池獲取可用連接.可以指定客戶程序能夠等待的最長時(shí)間
               * 參見前一個(gè)getConnection()方法.
               *
               * 
          @param timeout 以毫秒計(jì)的等待時(shí)間限制
               
          */

              
          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()返回的原因是超時(shí)
                    return null;
                  }

                }

                
          return con;
              }


              
          /**
               * 關(guān)閉所有連接
               
          */

              
          public synchronized void release() {
                Enumeration allConnections 
          = freeConnections.elements();
                
          while (allConnections.hasMoreElements()) {
                  Connection con 
          = (Connection) allConnections.nextElement();
                  
          try {
                    con.close();
                    log(
          "關(guān)閉連接池" + name + "中的一個(gè)連接");
                  }

                  
          catch (SQLException e) {
                    log(e, 
          "無法關(guān)閉連接池" + name + "中的連接");
                  }

                }

                freeConnections.removeAllElements();
              }


              
          /**
               * 創(chuàng)建新的連接
               /*
          */

               
          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 閱讀(322) 評論(0)  編輯  收藏 所屬分類: JAVA

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

          導(dǎo)航

          統(tǒng)計(jì)

          公告

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

          常用鏈接

          留言簿(2)

          隨筆分類

          隨筆檔案

          收藏夾

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 明光市| 汤原县| 青海省| 海林市| 辽源市| 麟游县| 漳浦县| 云阳县| 彩票| 英吉沙县| 南昌市| 精河县| 麻阳| 汨罗市| 忻城县| 余姚市| 林周县| 枣强县| 垫江县| 井陉县| 商丘市| 织金县| 花莲市| 宁都县| 葵青区| 泽库县| 九龙城区| 墨玉县| 扎囊县| 蒙阴县| 慈溪市| 蒙自县| 龙山县| 淮北市| 和林格尔县| 永定县| 汉源县| 河西区| 蒙山县| 丹巴县| 师宗县|