1. 程式人生 > >經典的java自定義資料庫連線池程式碼

經典的java自定義資料庫連線池程式碼

import java.sql.Connection;   
import java.sql.DatabaseMetaData;   
import java.sql.Driver;   
import java.sql.DriverManager;   
import java.sql.ResultSet;   
import java.sql.SQLException;   
import java.sql.Statement;   
import java.util.Enumeration;   
import java.util.Vector;   
  
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 型    
    public ConnectionPool() {          
    }   
       
    /**  
     *   
     * 建構函式  
     *   
     * @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;   
  
    }   
  
    /**  
     * 建立一個數據庫連線池,連線池中的可用連線的數量採用類成員 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  
     *            要建立的資料庫連線的數目    
     */  
  
    @SuppressWarnings("unchecked")   
    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 enumerate = connections.elements();   
  
        // 遍歷所有的物件,看是否有可用的連線   
        while (enumerate.hasMoreElements()) {   
            pConn = (PooledConnection) enumerate.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();   
                ResultSet rs = stmt.executeQuery("select count(*) from "   + testTable);   
                rs.next();   
                System.out.println(testTable + ":表的記錄數為:" + rs.getInt(1));   
  
            }   
  
        } catch (SQLException e) {   
            // 上面丟擲異常,此連線己不可用,關閉它,並返回 false;   
            e.printStackTrace();            
            closeConnection(conn);   
            return false;   
  
        }   
  
        // 連線可用,返回 true   
  
        return true;   
  
    }   
  
    /**  
     * 此函式返回一個數據庫連線到連線池中,並把此連線置為空閒。  
     *   
     * 所有使用連線池獲得的資料庫連線均應在不使用此連線時返回它。  
     *   
     * @param 需返回到連線池中的連線物件  
     */  
  
    public void returnConnection(Connection conn) {   
  
        // 確保連線池存在,如果連線沒有建立(不存在),直接返回   
        if (connections == null) {   
            System.out.println(" 連線池不存在,無法返回此連線到連線池中 !");   
            return;   
        }   
  
        PooledConnection pConn = null;   
        Enumeration enumerate = connections.elements();   
        // 遍歷連線池中的所有連線,找到這個要返回的連線物件   
        while (enumerate.hasMoreElements()) {   
  
            pConn = (PooledConnection) enumerate.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 enumerate = connections.elements();   
        while (enumerate.hasMoreElements()) {   
  
            // 獲得一個連線物件   
            pConn = (PooledConnection) enumerate.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 enumerate = connections.elements();   
        while (enumerate.hasMoreElements()) {   
            pConn = (PooledConnection) enumerate.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) {   
        }   
    }   
  
    /**  
     * 返回連線池的初始大小  
     *   
     * @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;    
    }   
  
    /**  
     * 內部使用的用於儲存連線池中連線物件的類  
     *   
     * 此類中有兩個成員,一個是資料庫的連線,另一個是指示此連線是否  
     *   
     * 正在使用的標誌。  
     */  
  
    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;   
        }   
  
    }   
  
}  
import java.sql.Connection;   
  
public class ConnectionPoolTest {   
  
    public static void main(String[] args) throws Exception {   
        ConnectionPool connPool = new ConnectionPool("oracle.jdbc.driver.OracleDriver","jdbc:oracle:thin:@127.0.0.1:1521:ORCL","scott","tiger");   
        connPool.createPool();   
        Connection conn = connPool.getConnection();   
        connPool.closeConnectionPool();   
        connPool.setTestTable("EMP");   
    }         
}  


相關推薦

經典java定義資料庫連線程式碼

import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.Driver; import java.sql.DriverManager; import j

定義資料庫連線實現方式 MySQL

應用程式直接獲取資料庫連線缺點 使用者每次請求都會建立一次資料庫連線,並且資料庫建立連線會消耗相對大的資源和時間。 如果針對於個別的工具或者是大量的程式碼測試甚至系統執行,對資料庫操作次數頻繁,極大的佔用資料庫資源,有可能會發生宕機或者記憶體溢位的現象。 而在大多的專案中,常常用到阿里巴

定義資料庫連線實現方式 MySQL

應用程式直接獲取資料庫連線缺點 使用者每次請求都會建立一次資料庫連線,並且資料庫建立連線會消耗相對大的資源和時間。 如果針對於個別的工具或者是大量的程式碼測試甚至系統執行,對資料庫操作次數頻繁,極大的佔用資料庫資源,有可能會發生宕機或者記憶體溢位的現象。 而在大多的專案中

(二十)定義資料庫連線

目錄 使用資料庫連線池優化資料庫效能 之前我們對資料庫的操作,其實是有很大問題的; 因為我們是每次操作資料庫之前,都會問資料庫要一個連線,用完之後,就把這個連結還給了資料庫; 其實資料庫連線是重量級的東西,資料庫每次建立一個連接出來,都要花

java資料庫連線程式碼實現

import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.uti

java建立資料庫連線程式碼

       資料庫連線池(Connection pooling)是程式啟動時建立足夠的資料庫連線,並將這些連線組成一個連線池,由程式動態地對池中的連線進行申請,使用,釋放。        大家可以想一下,如果專案中沒有資料庫連線池會是一個什麼樣的結果?每訪問一次資料庫

Java 定義線程

dfa and hand blank epo cte 方法的參數 factor handler Java 自定義線程池 https://www.cnblogs.com/yaoxiaowen/p/6576898.html public ThreadPoolExecutor(i

JAVA基礎26-資料庫連線

資料庫連線池         資料庫連線池負責分配,管理,釋放資料庫連線,它允許應用程式重複使用一個現有的資料庫連線,而不是重新建立一個。 編寫資料庫連線池 編寫資料庫連線池必須實現java.sql.DataSource介面 在Da

Tomcat9 + java + mysql 配置資料庫連線

今天看到書上MyEclipse配置資料庫連線池,搞了好久不成功,上網Google了好久,先是自己手動部署網站,在網上看的都是把web.xml和context.xml放在WEB-INF資料夾下,怎麼也不

java定義執行緒--ThreadPoolExecutors

public class MyThreadPool { public static void main(String[] args) { /** * 1.在使用有界佇列的時候:若有新的任務需要執行,如果執行緒池實際執行緒數小於corePoolSize核心執行緒數的時候,則優先建立執行緒。

Java定義執行緒和執行緒總數控制

1 概述池化是常見的思想,執行緒池是非常典型的池化的實現,《Java併發程式設計實戰》也大篇幅去講解了Java中的執行緒池。本文實現一個簡單的執行緒池。 2 核心類 【1】介面定義 public interface IThreadPool<Job extends

Java中的資料庫連線原理

連線池的基本工作原理 1、基本概念及原理 我們知道,對於共享資源,有一個很著名的設計模式:資源池(Resource Pool)。該模式正是為了解決資源的頻繁分配?釋放所造成的問題。資料庫連線池的基本思想就是為資料庫連線建立一個“緩衝池”。預先在緩衝池中放入一定數量的連

【CAS】定義資料庫連線配置

      在上一篇部落格中,對CAS進行了整體的介紹,我們知道,CAS可分為Server和Client。本篇部落格開始介紹對CAS  Sever進行的一些自定義配置。 【版本說明】:CAS Server 4.0 【下載地址】:https://github.com/aper

各種Java技術框架資料庫連線比較(一)

<c3p0-config> <default-config> <!--當連線池中的連線耗盡的時候c3p0一次同時獲取的連線數。Default: 3 --> <property name="acquireIncrement">3</property>

Java自學-JDBC 資料庫連線

## 資料庫連線池 與[執行緒池](http://how2j.cn/k/thread/thread-threadpool/357.html?p=43278)類似的,資料庫也有一個數據庫連線池。 不過他們的實現思路是不一樣的。 本章節講解了自定義資料庫連線池類:ConnectionPool,雖然不是很完善和

定義實現資料庫連線

資料庫連線池: >資料庫的連線物件建立工作,比較消耗效能 >一開始先在記憶體中開闢一塊空間(集合) , 先往池子裡面放置 多個連線物件。  後面需要連線的話,直接從池子裡面去。不要去自己建立連線了。  使用完畢, 要記得歸還連線。確保連線物件能迴圈利用。即建立

Java】Spring和Tomcat帶的連線實現資料庫操作

@[toc] 前言 前面我們已經用Spring和傳統的Jdbc實現資料庫操作、Spring和JdbcTemplate實現資料庫操作。但是這些都是基於直連的資料來源進行的,現在我們將介紹基於連線池的資料來源進行資料庫操作。前面幾個步驟都相同。 建立資料庫 首先建立我們的資料庫(這裡我使用的是Mysql)

Javaweb總結2—定義JDBC資料庫連線

什麼是資料庫連線池呢? 資料庫連線池簡而言之就是一個容器裡存放一些資料庫連線。 那問題來了,要資料庫連線池有什麼用呢? 哈哈不用急,接下來我們一起慢慢分析分析 我們仔細觀察這個連線池,有沒有解決剛剛開始的疑問呢? 實現連線池先繼承一個DataSourse類,當然也可以選擇不繼承它來寫

Druid連線定義資料庫密碼加解密的實現

Druid的功能 1、替換DBCP和C3P0。Druid提供了一個高效、功能強大、可擴充套件性好的資料庫連線池。 2、可以監控資料庫訪問效能,Druid內建提供了一個功能強大的StatFilter外掛,能夠詳細統計SQL的執行效能,這對於線上分析資料庫訪問效

java定義連線

1、java自定義連線池   1.1連線池的概念:    實際開發中"獲取連線"或“釋放資源”是非常消耗系統資源的兩個過程,為了姐姐此類效能問題,通常情況我們採用連線池技術來貢獻連線Connection    用池來管理Connection,這樣可以重複使用Connection,有了池,所以我們就不用自