1. 程式人生 > >Java資料庫連線池原理與簡易實現

Java資料庫連線池原理與簡易實現

1、什麼是資料庫連線池

    我們現在在開發中一定都會用到資料庫,為了提高我們的系統的訪問速度,資料庫優化是一個有效的途徑。我們現在開發中使用資料庫一般都要經歷以下的四個步驟:(1)載入資料庫的驅動類,(2)建立資料庫連線,(3)進行資料操作,(4)關閉資料庫連線;在這四步中建立資料庫連線是一個比較耗時的操作,如果每次有新的操作資料庫的需求都去重新建立資料庫連線必然要耗費一部分時間,拖慢系統的訪問速度;在這種情況下我們就需要資料庫連線池,預先建立好一定數量的資料庫連線,等我們現需要使用時直接從其中拿已經建立好了尚未使用的的資料庫連線,這樣就可以節省掉一部分時間,加快系統的訪問速度,儲存這些預先建立的一定數量的資料庫連線的容器稱之為資料庫連線池。

2、現有的常用資料庫連線池

    (1)DBCP資料庫連線池

    (2)C3P0資料庫連線池

3、資料庫連線池原理

    資料庫連線池通過預先建立一定數量的空閒的資料庫連線,在需要資料庫連線時直接從其中獲取,而不要去重新建立而節省一定的時間。

    資料庫連線池的連線有連個屬性,一個是本資料庫的真正的連線物件,一個是標誌本連線是否是空閒的標誌;當資料庫連線池被初始化的時候,會去建立一定數       量(一般在配置檔案中配置)的資料庫連線,並且這些連線都是處於空閒狀態的,當需要資料庫連線時,直接從資料庫連線池中獲取已經建立並且空閒的資料庫連               接  並將其致為非空閒狀態,如果資料庫連線池中沒有了空閒的連線,則去看資料庫連線池連線數量是否以達到最大值(一般在配置檔案中配置),如果沒有達到最            大 值則再去建立一定數量的空閒連線;當連線使用完畢後,並不真正的關閉連線,而是將連線的狀態重新致為空閒。從而達到連線重複使用的效果,節省時間。

4、簡易資料庫連線池的實現

  (1)、建立資料庫連線池的物件,物件包括真正的資料庫連線池物件和是否可用的標誌。

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 資料庫連線池物件
 */
public class SimplePoolEntity {

    //真正的資料庫連線物件
    private Connection connection;
    //是否可用的標誌,預設為true 可用
    private boolean isUsable = true;

    public Connection getConnection() {
        return connection;
    }

    public void setConnection(Connection connection) {
        this.connection = connection;
    }

    public boolean isUsable() {
        return isUsable;
    }

    public void setUsable(boolean usable) {
        isUsable = usable;
    }

    /**
     * 資料庫操作方法
     * @param sql  需要執行的sql語句
     * @return  ResultSet
     */
    public ResultSet execSql(String sql){
        ResultSet rs = null;
        try {
            Statement statement = connection.createStatement();
            rs =statement.executeQuery(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return rs;
    }
}

  (2)資料庫連線池操作介面

/**
* 資料庫連線池操作介面
*/
public interface SimplePoolService {
/**
* 連線池建立連線介面
* @param connCount 需要建立的連線數量
*/
void createConnection(int connCount) throws Exception;

/**
* 獲取資料庫連線
* @return
* @throws Exception
*/
SimplePoolEntity getConnection();
}

  (3)資料庫連線池操作實現

  資料庫連線池配置檔案:

#資料庫的驅動類
simple.jdbc.driver = com.mysql.jdbc.Driver
#資料庫的連線url
simple.jdbc.url = jdbc:mysql://localhost:3306/test
#資料庫的連線使用者名稱
simple.jdbc.username = root
#資料庫的連線密碼
simpel.jdbc.password = root
#資料庫連線池的初始化連線數量
simple.init.count = 10
#資料庫連線池的步進數量
simple.step.count = 4
#連線池的最大數量
simple.max.count = 100

  資料庫連線池的實現

/**
 * 資料庫操作實現
 * 本操作中將要實現資料庫連線池的初始化工作,初始化引數採用配置檔案的形式來進行配置
 *
 */
public class SimplePoolServiceImpl implements SimplePoolService {

    private String jdbcDriver; // 資料庫驅動
    private String jdbcUrl;  //資料庫url
    private String username; //使用者名稱
    private String password; //密碼
    private Integer initCount; //初始化數量
    private Integer stepCount;  //步進數量
    private Integer maxCount; //最大數量

    private SimplePoolEntity simplePoolEntity;
    private Set<SimplePoolEntity> simplePoolEntitySet = new HashSet<>();
    /**
     * 構造方法初始化 資料庫連線池
     */
    public SimplePoolServiceImpl(){
        init();
    }

    /**
     * 資料庫連線池初始化
     */
    private void init(){
        //1.讀取配置檔案
        InputStream in =this.getClass().getClassLoader().getResourceAsStream("simpleboolconfig.properties");
        Properties properties = new Properties();
        try {
            properties.load(in);
            //設定初始化引數
            jdbcDriver = properties.getProperty("simple.jdbc.driver");
            jdbcUrl  = properties.getProperty("simple.jdbc.url");
            username  = properties.getProperty("simple.jdbc.username");
            password  = properties.getProperty("simpel.jdbc.password");
            initCount  = Integer.parseInt(properties.getProperty("simple.init.count"));
            stepCount  =Integer.parseInt( properties.getProperty("simple.step.count"));
            maxCount  =Integer.parseInt( properties.getProperty("simple.max.count"));
            //載入資料庫驅動
            Driver  driver = (Driver) Class.forName(jdbcDriver).newInstance();
            //獲取資料庫管理物件
            DriverManager.deregisterDriver(driver);
            //初始化一定數量的連線
            createConnection(initCount);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    @Override
    public void createConnection(int connCount) throws Exception {
        //判斷資料庫連線池是否以達到最大連線數
        if(simplePoolEntitySet.size() + connCount > maxCount){
            throw new RuntimeException("連線池數量已到上限");
        }
        for (int i=0;i < connCount;i++){
            simplePoolEntity = new SimplePoolEntity();
            simplePoolEntity.setConnection(DriverManager.getConnection(jdbcUrl,username,password));
            simplePoolEntity.setUsable(true);
            simplePoolEntitySet.add(simplePoolEntity);
        }
    }

    @Override
    public SimplePoolEntity getConnection()  {
        try {
            SimplePoolEntity simplePoolEntity = getRealConection();
            //為空時建立新的連線
            while (simplePoolEntity == null){
                createConnection(stepCount);
                //建立連線比較耗時,建議在此處讓執行緒延遲一定時間
                Thread.sleep(3000);
                simplePoolEntity = getRealConection();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return simplePoolEntity;
    }

    private SimplePoolEntity getRealConection() throws Exception{
        //迴圈連線池,獲取連線
        for(SimplePoolEntity simplePoolEntity : simplePoolEntitySet){
            //判斷是否為空閒
            if(simplePoolEntity.isUsable()){
                //判斷連線是否有效
                if(!simplePoolEntity.getConnection().isValid(3000)){
                    //無效連線,重新建立連線替換該連線
                    Connection realConnect = DriverManager.getConnection(jdbcUrl,username,password);
                    simplePoolEntity.setConnection(realConnect);
                }
                //設定狀態為不可用
                simplePoolEntity.setUsable(false);
                return simplePoolEntity;
            }
        }
        return null;
    }
}

  (4) 對外提供單例模式的資料庫連線池管理物件

public class SimplePoolManger {
    //私有化構造,禁止建立
    private SimplePoolManger(){}

    //在靜態內部類中例項化物件,達到懶漢單例模式
    private static class ClassLoad{
         public static SimplePoolService getSimplePoolService(){
             return  new SimplePoolServiceImpl();
         }
    }
    public static SimplePoolService getInstace(){
        return ClassLoad.getSimplePoolService();
    }
}

相關推薦

Java資料庫連線原理簡易實現

1、什麼是資料庫連線池     我們現在在開發中一定都會用到資料庫,為了提高我們的系統的訪問速度,資料庫優化是一個有效的途徑。我們現在開發中使用資料庫一般都要經歷以下的四個步驟:(1)載入資料庫的驅動類,(2)建立資料庫連線,(3)進行資料操作,(4)關閉資料庫連線;在這四步中建立資料庫連線是一個比較耗時的操

JAVA和C#中資料庫連線原理應用

JAVA和C#中資料庫連線池原理 在現在的網際網路發展中,高併發成為了主流,而最關鍵的部分就是對資料庫操作和訪問,在現在的網際網路發展中,ORM框架曾出不窮, 比如:.Net-Core的EFCore、SqlSugar、Dapper。JAVA的Spring-DataJpa(EntityManager),Myba

主流Java資料庫連線比較開發配置實戰

1.資料庫連線池概述 資料庫連線的建立是一種耗時、效能低、代價高的操作,頻繁的資料庫連線的建立和關閉極大的影響了系統的效能。資料庫連線池是系統初始化過程中建立一定數量的資料庫連線放於連線池中,當程式需要訪問資料庫時,不再建立一個新的連線,而是從連線池中取出一個已建立的空

淺析資料庫連線原理分析實現

1 動機在專案初期對於資料庫的使用就是開啟一個連線並進行使用,使用過後關閉連線釋放資源,並且在後臺簡單測試中,並沒有出現問題。但是在與前端對接之後,發現頻繁地開啟和關閉連線會對效能造成很大的影響,而且之前假設的情況是接受的請求都是同步的,但是前端可能傳送非同步請求,當兩個請求

資料庫連線原理詳解自定義連線實現

實現原理資料庫連線池在初始化時將建立一定數量的資料庫連線放到連線池中,這些資料庫連線的數量是由最小資料庫連線數制約。無論這些資料庫連線是否被使用,連線池都將一直保證至少擁有這麼多的連線數量。連線池的最大資料庫連線數量限定了這個連線池能佔有的最大連線數,當應用程式向連線池請求的連

java資料庫連線實現原理

原文:http://blog.csdn.net/frightingforambition/article/details/25464129  一、為什麼在連線資料庫時要使用連線池  資料庫連線是一種關鍵的有限的昂貴的資源,這一點在多使用者的網頁應用程式中體現得

Java資料庫連線實現(不用框架)

前言:因為需要正式做專案,瞭解到了連線池這個東西。在網上找了很多資料,發現都是大同小異,各種轉載,看上去搜出來了幾十個答案,結果很可能是同一個。並且大多都是基於框架的資料庫連線池。可是我只是想採用MVC做一個不是很大的專案,不需要使用到框架啊。這可怎麼辦,最後沒

Java中的資料庫連線原理

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

Java資料庫連線原理機制的詳細講解

連線池的基本工作原理   1、基本概念及原理   由上面的分析可以看出,問題的根源就在於對資料庫連線資源的低效管理。我們知道,對於共享資源,有一個很著名的設計模式:資源池 (Resource Pool)。該模式正是為了解決資源的頻繁分配?釋放所造成的問題。為解決上述問

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資料庫連線細節探討

我們知道,資料庫連線池可以把資料庫的連線快取起來,下次使用的話可以直接取到快取起來的資料庫連線。那麼,在這個過程中有幾個細節需要注意: 1、資料庫的連線數有沒有限制? 2、資料庫會不會自動斷開已經建立的連線? 3、如果資料庫重啟了,但應用沒有重啟,那麼資料庫連線池中的所有連線都不可用了,

HikariCP 的Java資料庫連線介紹及配置

HiKariCP是資料庫連線池的一個後起之秀,號稱效能最好,可以完美地PK掉其他連線池。 原文地址:http://blog.csdn.net/clementad/article/details/46928621 官網:https://github.com/brettwooldridge/Hi

資料庫連線原理及應用

1、運作原理 在實際應用開發中,特別是在WEB應用系統中,如果JSP、Servlet或EJB使用 JDBC直接訪問資料庫中的資料,每一次資料訪問請求都必須經歷建立資料庫連線、開啟資料庫、存取資料和關閉資料庫連線等步驟,而連線並開啟資料庫是一件既消耗資源又費時的工作,如果頻繁發生這種資料庫操作,系

物件資料庫連線原理

一、一點說明: (本文的知識點來自C#執行緒參考手冊) 物件池在企業軟體中非常常見,為了提供應用的效能,必須控制物件例項的建立。比如建立資料庫連線物件,每一次建立的代價非常高昂,每一次使用資料庫都需要連線資料庫,代價非常高昂,因此有了資料庫連線池,每一次一個連線被建立之後不是就馬上釋放,下一次使用的時候重

Java資料庫連線

1.簡介 Java 獲取資料庫的基本方式有兩種:1,通過DriverManager;2,通過DataSource,這裡主要講述第二種。 1.1 DriverManager跟DataSource獲取getConnection 的區別 DriverManag

索引優先佇列的工作原理簡易實現

歡迎探討,如有錯誤敬請指正 1. 優先佇列與索引優先佇列 優先佇列的原理大家應該比較熟悉,本質上就是利用完全二叉樹的結構實現以log2n的時間複雜度刪除佇列中的最小物件(這裡以小堆頂為例)。完全二叉樹又可以通過陣列下標實現索引,當插入一個物件的時候,利用上浮操作更新最小物件。當刪除堆頂最小物件時,將末尾

為什麼HikariCP被號稱為效能最好的Java資料庫連線,如何配置使用

HiKariCP是資料庫連線池的一個後起之秀,號稱效能最好,可以完美地PK掉其他連線池。 什麼?不是有C3P0/DBCP這些成熟的資料庫連線池嗎?一直用的好好的,為什麼又搞出一個BoneCP來?因為,傳說中BoneCP在快速這個特點上做到了極致,官方資料是C3P0等

Java資料庫連線比較(c3p0,dbcp,proxool和BoneCP)

詳見:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp21 Java框架資料庫連線池比較(c3p0,dbcp和proxool,BoneC) 現在常用的開源資料連線池主要有c3p0,dbcp,proxool

Java資料庫連線比較及使用場景

我們在連線資料庫的時候,由於建立資料庫連線代價很大(銷燬連線的代價也很大),需要消耗很多資源,因此引入資料庫連線池。資料庫連線池是一種池化技術,預先建立好資料庫連線,儲存在記憶體中,當需要連線時,從中取出即可,使用完後放回連線池。 下面我們介紹Java中常用的

Java資料庫連線幾種方式及其特點

主流的資料庫連線池  在目前技術前沿比較流行的資料庫連線池有:DBCP、Tomcat Jdbc Pool、BoneCP、Druid、C3P0等 DBCP:由Apache開發的一個Java資料庫連線池專案, Jakarta commons-pool物件池機制,Tomcat使