<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    gembin

    OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

    HBase, Hadoop, ZooKeeper, Cassandra

    Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

    There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

    About Me

     

    一個經試用效果非常不錯的數據庫連接池

    一個經試用效果非常不錯的數據庫連接池
     

    前言:

        雖說現在許多企業級的應用服務器均自己帶有數據庫連接池功能,就連 Tomcat 也支持了這種功能。然而在許多時候,我們還是要使用數據庫連接池,如:訪問數據庫的 Java 桌面應用程序等。這個數據庫連接池是我根據《 Inside Servlets 》一書中的示例改寫而成,經過試用,效果非常不錯。特發布共享。

     

     源代碼

     

    //ConnectionPool.java 
    
    package com.abner.dbconnector; 
    
    import java.sql.*; 
    
    import java.util.*; 
    
    /** 
    
    * ConnectionPool 類創建了一個對特定數據庫指定大小的連接池。連接池對象 
    
    * 允許客戶端指定 JDBC 驅動程序,數據庫,使用數據庫的用戶名和密碼。而且, 
    
    * 客戶端能指定連接池的在初始創建是產生數據庫連接的數量,和指定當連接 
    
    * 不夠時每次自動增加連接的數量及連接池最多的數據庫連接的數量。 
    
    * 
    
    * 對外提供的方法有: ConnectionPool :構造函數 
    
    * getInitialConnections: 返回連接池初始化大小 
    
    * setInitialConnections: 設置連接池初始化大小 
    
    * getIncrementalConnections: 返回連接池自動增加的增量 
    
    * setIncrementalConnections: 設置連接池自動增加的大小 
    
    * getMaxConnections :獲得連接池的最大可允許的連接數 
    
    * setMaxConnections :設置連接池的最大可允許的連接數 
    
    * getTestTable :獲得測試表的名字 
    
    * setTestTable :設置測試表的名字 
    
    * createPool: 創建連接池 , 線程己同步 
    
    * getConnection: 從連接池中獲得一個數據庫連接 
    
    * returnConnection: 返回一個連接到連接池中 
    
    * refreshConnections: 刷新連接池 
    
    * closeConnectionPool: 關閉連接池 
    
    * 
    
    * 
    
    * @author abnerchai Email: josserchai@yahoo.com 
    
    * @version 1.0.0 
    
    * 
    
    */ 
    
    public class ConnectionPool { 
    
       private String jdbcDriver = ""; // 數據庫驅動 
    
       private String dbUrl = ""; // 數據 URL 
    
       private String dbUsername = ""; // 數據庫用戶名 
    
       private String dbPassword = ""; // 數據庫用戶密碼 
    
       private String testTable = ""; // 測試連接是否可用的測試表名,默認沒有測試表 
    
       private int initialConnections = 10; // 連接池的初始大小 
    
       private int incrementalConnections = 5;// 連接池自動增加的大小 
    
       private int maxConnections = 50; // 連接池最大的大小 
    
       private Vector connections = null; // 存放連接池中數據庫連接的向量 , 初始時為 null 
    
    // 它中存放的對象為 PooledConnection 型 
    
    /** 
    
    * 構造函數 
    
    * 
    
    * @param jdbcDriver String JDBC 驅動類串 
    
    * @param dbUrl String 數據庫 URL 
    
    * @param dbUsername String 連接數據庫用戶名 
    
    * @param dbPassword String 連接數據庫用戶的密碼 
    
    * 
    
    */ 
    
    public ConnectionPool(String jdbcDriver,String dbUrl,String dbUsername,String dbPassword) { 
    
       this.jdbcDriver = jdbcDriver; 
    
       this.dbUrl = dbUrl; 
    
       this.dbUsername = dbUsername; 
    
       this.dbPassword = dbPassword; 
    
    } 
    
    /** 
    
    * 返回連接池的初始大小 
    
    * 
    
    * @return 初始連接池中可獲得的連接數量 
    
    */ 
    
    public int getInitialConnections() { 
    
       return this.initialConnections; 
    
    } 
    
    /** 
    
    * 設置連接池的初始大小 
    
    * 
    
    * @param 用于設置初始連接池中連接的數量 
    
    */ 
    
    public void setInitialConnections(int initialConnections) { 
    
       this.initialConnections = initialConnections; 
    
    } 
    
    /** 
    
    * 返回連接池自動增加的大小 、 
    
    * 
    
    * @return 連接池自動增加的大小 
    
    */ 
    
    public int getIncrementalConnections() { 
    
       return this.incrementalConnections; 
    
    } 
    
    /** 
    
    * 設置連接池自動增加的大小 
    
    * @param 連接池自動增加的大小 
    
    */ 
    
    public void setIncrementalConnections(int incrementalConnections) { 
    
       this.incrementalConnections = incrementalConnections; 
    
    } 
    
    /** 
    
    * 返回連接池中最大的可用連接數量 
    
    * @return 連接池中最大的可用連接數量 
    
    */ 
    
    public int getMaxConnections() { 
    
       return this.maxConnections; 
    
    } 
    
    /** 
    
    * 設置連接池中最大可用的連接數量 
    
    * 
    
    * @param 設置連接池中最大可用的連接數量值 
    
    */ 
    
    public void setMaxConnections(int maxConnections) { 
    
       this.maxConnections = maxConnections; 
    
    } 
    
    /** 
    
    * 獲取測試數據庫表的名字 
    
    * 
    
    * @return 測試數據庫表的名字 
    
    */ 
    
    public String getTestTable() { 
    
       return this.testTable; 
    
    } 
    
    /** 
    
    * 設置測試表的名字 
    
    * @param testTable String 測試表的名字 
    
    */ 
    
    public void setTestTable(String testTable) { 
    
       this.testTable = testTable; 
    
    } 
    
    /** 
    
    * 
    
    * 創建一個數據庫連接池,連接池中的可用連接的數量采用類成員 
    
    * initialConnections 中設置的值 
    
    */ 
    
    public synchronized void createPool() throws Exception { 
    
    // 確保連接池沒有創建 
    
    // 如果連接池己經創建了,保存連接的向量 connections 不會為空 
    
    if (connections != null) { 
    
        return; // 如果己經創建,則返回 
    
    } 
    
    // 實例化 JDBC Driver 中指定的驅動類實例 
    
    Driver driver = (Driver) (Class.forName(this.jdbcDriver).newInstance()); 
    
    DriverManager.registerDriver(driver); // 注冊 JDBC 驅動程序 
    
    // 創建保存連接的向量 , 初始時有 0 個元素 
    
    connections = new Vector(); 
    
    // 根據 initialConnections 中設置的值,創建連接。 
    
    createConnections(this.initialConnections); 
    
        System.out.println(" 數據庫連接池創建成功! "); 
    
    } 
    
    /** 
    
    * 創建由 numConnections 指定數目的數據庫連接 , 并把這些連接 
    
    * 放入 connections 向量中 
    
    * 
    
    * @param numConnections 要創建的數據庫連接的數目 
    
    */ 
    
    private void createConnections(int numConnections) throws SQLException { 
    
    // 循環創建指定數目的數據庫連接 
    
    for (int x = 0; x < numConnections; x++) { 
    
    // 是否連接池中的數據庫連接的數量己經達到最大?最大值由類成員 maxConnections 
    
    // 指出,如果 maxConnections 為 0 或負數,表示連接數量沒有限制。 
    
    // 如果連接數己經達到最大,即退出。 
    
       if (this.maxConnections > 0 && this.connections.size() >= this.maxConnections) { 
    
          break; 
    
       } 
    
    //add a new PooledConnection object to connections vector 
    
    // 增加一個連接到連接池中(向量 connections 中) 
    
    try{ 
    
        connections.addElement(new PooledConnection(newConnection())); 
    
    }catch(SQLException e){ 
    
        System.out.println(" 創建數據庫連接失敗! "+e.getMessage()); 
    
        throw new SQLException(); 
    
    } 
    
        System.out.println(" 數據庫連接己創建 ......"); 
    
    } 
    
    } 
    
    /** 
    
    * 創建一個新的數據庫連接并返回它 
    
    * 
    
    * @return 返回一個新創建的數據庫連接 
    
    */ 
    
    private Connection newConnection() throws SQLException { 
    
    // 創建一個數據庫連接 
    
    Connection conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword); 
    
    // 如果這是第一次創建數據庫連接,即檢查數據庫,獲得此數據庫允許支持的 
    
    // 最大客戶連接數目 
    
    //connections.size()==0 表示目前沒有連接己被創建 
    
    if (connections.size() == 0) { 
    
       DatabaseMetaData metaData = conn.getMetaData(); 
    
       int driverMaxConnections = metaData.getMaxConnections(); 
    
    // 數據庫返回的 driverMaxConnections 若為 0 ,表示此數據庫沒有最大 
    
    // 連接限制,或數據庫的最大連接限制不知道 
    
    //driverMaxConnections 為返回的一個整數,表示此數據庫允許客戶連接的數目 
    
    // 如果連接池中設置的最大連接數量大于數據庫允許的連接數目 , 則置連接池的最大 
    
    // 連接數目為數據庫允許的最大數目 
    
        if (driverMaxConnections > 0 && this.maxConnections > driverMaxConnections) { 
    
          this.maxConnections = driverMaxConnections; 
    
        } 
    
    } 
    
    return conn; // 返回創建的新的數據庫連接 
    
    } 
    
    /** 
    
    * 通過調用 getFreeConnection() 函數返回一個可用的數據庫連接 , 
    
    * 如果當前沒有可用的數據庫連接,并且更多的數據庫連接不能創 
    
    * 建(如連接池大小的限制),此函數等待一會再嘗試獲取。 
    
    * 
    
    * @return 返回一個可用的數據庫連接對象 
    
    */ 
    
    public synchronized Connection getConnection() throws SQLException { 
    
    // 確保連接池己被創建 
    
    if (connections == null) { 
    
        return null; // 連接池還沒創建,則返回 null 
    
    } 
    
    Connection conn = getFreeConnection(); // 獲得一個可用的數據庫連接 
    
    // 如果目前沒有可以使用的連接,即所有的連接都在使用中 
    
    while (conn == null){ 
    
    // 等一會再試 
    
        wait(250); 
    
        conn = getFreeConnection(); // 重新再試,直到獲得可用的連接,如果 
    
    //getFreeConnection() 返回的為 null 
    
    // 則表明創建一批連接后也不可獲得可用連接 
    
    } 
    
    return conn;// 返回獲得的可用的連接 
    
    } 
    
    /** 
    
    * 本函數從連接池向量 connections 中返回一個可用的的數據庫連接,如果 
    
    * 當前沒有可用的數據庫連接,本函數則根據 incrementalConnections 設置 
    
    * 的值創建幾個數據庫連接,并放入連接池中。 
    
    * 如果創建后,所有的連接仍都在使用中,則返回 null 
    
    * @return 返回一個可用的數據庫連接 
    
    */ 
    
    private Connection getFreeConnection() throws SQLException { 
    
    // 從連接池中獲得一個可用的數據庫連接 
    
    Connection conn = findFreeConnection(); 
    
    if (conn == null) { 
    
    // 如果目前連接池中沒有可用的連接 
    
    // 創建一些連接 
    
    createConnections(incrementalConnections); 
    
    // 重新從池中查找是否有可用連接 
    
    conn = findFreeConnection(); 
    
    if (conn == null) { 
    
    // 如果創建連接后仍獲得不到可用的連接,則返回 null 
    
       return null; 
    
    } 
    
    } 
    
    return conn; 
    
    } 
    
    /** 
    
    * 查找連接池中所有的連接,查找一個可用的數據庫連接, 
    
    * 如果沒有可用的連接,返回 null 
    
    * 
    
    * @return 返回一個可用的數據庫連接 
    
    */ 
    
    private Connection findFreeConnection() throws SQLException { 
    
    Connection conn = null; 
    
    PooledConnection pConn = null; 
    
    // 獲得連接池向量中所有的對象 
    
    Enumeration en = connections.elements(); 
    
    // 遍歷所有的對象,看是否有可用的連接 
    
    while (en.hasMoreElements()) { 
    
       pConn = (PooledConnection) en.nextElement(); 
    
       if (!pConn.isBusy()) { 
    
        // 如果此對象不忙,則獲得它的數據庫連接并把它設為忙 
    
        conn = pConn.getConnection(); 
    
        pConn.setBusy(true); 
    
        // 測試此連接是否可用 
    
        if (!testConnection(conn)) { 
    
         // 如果此連接不可再用了,則創建一個新的連接, 
    
         // 并替換此不可用的連接對象,如果創建失敗,返回 null 
    
         try{ 
    
           conn = newConnection(); 
    
         }catch(SQLException e){ 
    
           System.out.println(" 創建數據庫連接失敗! "+e.getMessage()); 
    
           return null; 
    
         } 
    
          pConn.setConnection(conn); 
    
       } 
    
       break; // 己經找到一個可用的連接,退出 
    
    } 
    
    } 
    
    return conn;// 返回找到到的可用連接 
    
    } 
    
    /** 
    
    * 測試一個連接是否可用,如果不可用,關掉它并返回 false 
    
    * 否則可用返回 true 
    
    * 
    
    * @param conn 需要測試的數據庫連接 
    
    * @return 返回 true 表示此連接可用, false 表示不可用 
    
    */ 
    
    private boolean testConnection(Connection conn) { 
    
    try { 
    
       // 判斷測試表是否存在 
    
       if (testTable.equals("")) { 
    
         // 如果測試表為空,試著使用此連接的 setAutoCommit() 方法 
    
         // 來判斷連接否可用(此方法只在部分數據庫可用,如果不可用 , 
    
         // 拋出異常)。注意:使用測試表的方法更可靠 
    
         conn.setAutoCommit(true); 
    
       } else {// 有測試表的時候使用測試表測試 
    
         //check if this connection is valid 
    
         Statement stmt = conn.createStatement(); 
    
         stmt.execute("select count(*) from " + testTable); 
    
    } 
    
    } catch (SQLException e) { 
    
    // 上面拋出異常,此連接己不可用,關閉它,并返回 false; 
    
    closeConnection(conn); 
    
    return false; 
    
    } 
    
    // 連接可用,返回 true 
    
    return true; 
    
    } 
    
    /** 
    
    * 此函數返回一個數據庫連接到連接池中,并把此連接置為空閑。 
    
    * 所有使用連接池獲得的數據庫連接均應在不使用此連接時返回它。 
    
    * 
    
    * @param 需返回到連接池中的連接對象 
    
    */ 
    
    public void returnConnection(Connection conn) { 
    
    // 確保連接池存在,如果連接沒有創建(不存在),直接返回 
    
    if (connections == null) { 
    
    System.out.println(" 連接池不存在,無法返回此連接到連接池中 !"); 
    
    return; 
    
    } 
    
    PooledConnection pConn = null; 
    
    Enumeration en = connections.elements(); 
    
    // 遍歷連接池中的所有連接,找到這個要返回的連接對象 
    
    while (en.hasMoreElements()) { 
    
    pConn = (PooledConnection) en.nextElement(); 
    
    // 先找到連接池中的要返回的連接對象 
    
    if (conn == pConn.getConnection()) { 
    
    // 找到了 , 設置此連接為空閑狀態 
    
    pConn.setBusy(false); 
    
    break; 
    
    } 
    
    } 
    
    } 
    
    /** 
    
    * 刷新連接池中所有的連接對象 
    
    * 
    
    */ 
    
    public synchronized void refreshConnections() throws SQLException { 
    
    // 確保連接池己創新存在 
    
    if (connections == null) { 
    
    System.out.println(" 連接池不存在,無法刷新 !"); 
    
    return; 
    
    } 
    
    PooledConnection pConn = null; 
    
    Enumeration en = connections.elements(); 
    
    while (en.hasMoreElements()) { 
    
    // 獲得一個連接對象 
    
    pConn = (PooledConnection) en.nextElement(); 
    
    // 如果對象忙則等 5 秒 ,5 秒后直接刷新 
    
    if (pConn.isBusy()) { 
    
    wait(5000); // 等 5 秒 
    
    } 
    
    // 關閉此連接,用一個新的連接代替它。 
    
    closeConnection(pConn.getConnection()); 
    
    pConn.setConnection(newConnection()); 
    
    pConn.setBusy(false); 
    
    } 
    
    } 
    
    /** 
    
    * 關閉連接池中所有的連接,并清空連接池。 
    
    */ 
    
    public synchronized void closeConnectionPool() throws SQLException { 
    
    // 確保連接池存在,如果不存在,返回 
    
    if (connections == null) { 
    
       System.out.println(" 連接池不存在,無法關閉 !"); 
    
       return; 
    
    } 
    
    PooledConnection pConn = null; 
    
    Enumeration en = connections.elements(); 
    
    while (en.hasMoreElements()) { 
    
       pConn = (PooledConnection) en.nextElement(); 
    
    // 如果忙,等 5 秒 
    
       if (pConn.isBusy()) { 
    
          wait(5000); // 等 5 秒 
    
        } 
    
    //5 秒后直接關閉它 
    
    closeConnection(pConn.getConnection()); 
    
    // 從連接池向量中刪除它 
    
    connections.removeElement(pConn); 
    
    } 
    
    // 置連接池為空 
    
    connections = null; 
    
    } 
    
    /** 
    
    * 關閉一個數據庫連接 
    
    * 
    
    * @param 需要關閉的數據庫連接 
    
    */ 
    
    private void closeConnection(Connection conn) { 
    
    try { 
    
    conn.close(); 
    
    }catch (SQLException e) { 
    
    System.out.println(" 關閉數據庫連接出錯: "+e.getMessage()); 
    
    } 
    
    } 
    
    /** 
    
    * 使程序等待給定的毫秒數 
    
    * 
    
    * @param 給定的毫秒數 
    
    */ 
    
    private void wait(int mSeconds) { 
    
    try { 
    
    Thread.sleep(mSeconds); 
    
    } catch (InterruptedException e) { 
    
    } 
    
    } 
    
    /** 
    
    * 
    
    * 內部使用的用于保存連接池中連接對象的類 
    
    * 此類中有兩個成員,一個是數據庫的連接,另一個是指示此連接是否 
    
    * 正在使用的標志。 
    
    */ 
    
    class PooledConnection { 
    
       Connection connection = null;// 數據庫連接 
    
       boolean busy = false; // 此連接是否正在使用的標志,默認沒有正在使用 
    
       // 構造函數,根據一個 Connection 構告一個 PooledConnection 對象 
    
       public PooledConnection(Connection connection) { 
    
         this.connection = connection; 
    
        } 
    
        // 返回此對象中的連接 
    
        public Connection getConnection() { 
    
          return connection; 
    
        } 
    
    // 設置此對象的,連接 
    
    public void setConnection(Connection connection) { 
    
       this.connection = connection; 
    
    } 
    
    // 獲得對象連接是否忙 
    
    public boolean isBusy() { 
    
       return busy; 
    
    } 
    
    // 設置對象的連接正在忙 
    
    public void setBusy(boolean busy) { 
    
       this.busy = busy; 
    
    } 
    
    } 
    
    } 
    
    這個程序所有的解釋我都詳細地寫在了源程序中,我想就不必多解說了吧。

    如果你有改進或修改,請保留原作者的聲明

    posted on 2007-09-21 10:47 gembin 閱讀(2957) 評論(1)  編輯  收藏

    評論

    # re: 一個經試用效果非常不錯的數據庫連接池 2007-09-22 00:15 千里冰封

    真的?哪天用用看  回復  更多評論   


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     

    導航

    統計

    常用鏈接

    留言簿(6)

    隨筆分類(440)

    隨筆檔案(378)

    文章檔案(6)

    新聞檔案(1)

    相冊

    收藏夾(9)

    Adobe

    Android

    AS3

    Blog-Links

    Build

    Design Pattern

    Eclipse

    Favorite Links

    Flickr

    Game Dev

    HBase

    Identity Management

    IT resources

    JEE

    Language

    OpenID

    OSGi

    SOA

    Version Control

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    free counters
    主站蜘蛛池模板: 亚洲高清视频免费| 免费人成在线观看网站视频| 在线观看日本亚洲一区| 凹凸精品视频分类国产品免费| 国产日韩久久免费影院| 亚洲日产2021三区在线| 亚洲区日韩区无码区| 7x7x7x免费在线观看| 亚洲精品久久久久无码AV片软件| 77777亚洲午夜久久多人| 四虎成年永久免费网站| 四虎影视在线看免费观看| 亚洲精品国产成人| 亚洲电影日韩精品| 美女视频黄的全免费视频 | 午夜在线免费视频| 亚洲美免无码中文字幕在线| 国产jizzjizz视频免费看| 99精品免费观看| 窝窝影视午夜看片免费| 亚洲va在线va天堂va手机| 亚洲人成伊人成综合网久久久 | 亚洲精品动漫免费二区| 精品国产免费人成网站| 亚洲国产精华液2020| 亚洲AV无码乱码国产麻豆穿越| 国产一级淫片a免费播放口之| 蜜桃AV无码免费看永久| 巨胸喷奶水视频www免费视频| 亚洲日本一线产区和二线 | 国产一级高清免费观看| h在线观看视频免费网站| 精品国产福利尤物免费| 黄网站色视频免费看无下截| 亚洲另类春色校园小说| 亚洲AV无码成人网站久久精品大 | 狠狠色香婷婷久久亚洲精品| 无码乱人伦一区二区亚洲一| 亚洲另类少妇17p| 国产免费观看视频| 男女交性永久免费视频播放|