程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 基於JDBC的數據庫連接池技術研究與設計

基於JDBC的數據庫連接池技術研究與設計

編輯:關於JAVA

摘 要 本文介紹了基於JDBC的數據庫連接池的工作原理,闡述了連接池技術 的事務處理、多數據庫服務器等各項關鍵技術,提出了一個高效的連接池管理策 略,最後詳細說明了數據庫連接池應用的具體實現過程。

關鍵詞 JDBC; 數據庫; 連接池; 事務處理

隨著信息技術的高速發展與廣泛應用,數據庫技術在信息技術領域中的位置 越來越重要,尤其是網絡應用和電子商務的迅速發展,都需要數據庫技術支持動 態Web站點的運行,而傳統的開發模式是:首先在主程序(如Servlet、Beans) 中建立數據庫連接;然後進行SQL操作,對數據庫中的對象進行查詢、修改和刪 除等操作;最後斷開數據庫連接。使用這種開發模式,對於一個簡單的數據庫應 用,由於數據庫的訪問不是很頻繁,只需要在訪問數據庫時創建一個連接,用完 後就關閉它,這樣做不會明顯的增大系統的開銷。但是對於一個復雜的數據庫應 用,情況就完全不同:頻繁的建立、關閉數據庫,會極大的降低系統的性能,增 大系統的開銷,甚至成為系統的瓶頸。另外使用這種傳統的模式,還必須管理數 據庫的每一個連接,以確保他們能正確關閉,如果出現程序異常而導致某些連接 未能關閉,將引起數據庫系統中的內存洩露,最終不得不重啟數據庫。因此采用 運行速度更快、數據庫訪問效率更高的數據庫技術,以提高系統的運行效率將是 至關重要的。

為了解決這一問題,在JDBC2.0中提出了JDBC連接池技術,通過在客戶之間共 享一組連接,而不是在它們需要的時候再為它們生成,這樣就可以改善資源使用 ,提高應用程序的響應能力。

JDBC 概述

JDBC(Java Database Connectivity,Java數據庫連接)是一種用於執行SQL 語句的JavaAPI,可以為多種關系型數據庫(如Oracle、Sybase、SQL Server、 Access等)提供統一訪問接口,它由一組Java語言編寫的類和接口組成,使數據 庫開發人員能夠用標准JavaAPI編寫數據庫應用程序。

連接池技術

1、連接池原理

連接池技術的核心思想是:連接復用,通過建立一個數據庫連接池以及一套 連接使用、分配、管理策略,使得該連接池中的連接可以得到高效、安全的復用 ,避免了數據庫連接頻繁建立、關閉的開銷。另外,由於對JDBC中的原始連接進 行了封裝,從而方便了數據庫應用對於連接的使用(特別是對於事務處理),提 高了開發效率,也正是因為這個封裝層的存在,隔離了應用的本身的處理邏輯和 具體數據庫訪問邏輯,使應用本身的復用成為可能。連接池主要由三部分組成( 如圖1所示):連接池的建立、連接池中連接的使用管理、連接池的關閉。下面 就著重討論這三部分及連接池的配置問題。

圖1 連接池模式

1.1 連接池的建立

應用程序中建立的連接池其實是一個靜態的。所謂靜態連接池是指連接池中 的連接在系統初始化時就已分配好,且不能隨意關閉連接。Java中提供了很多容 器類可以方便的構建連接池,如:Vector、Stack、Servlet、Bean等,通過讀取 連接屬性文件Connections.properties與數據庫實例建立連接。在系統初始化時 ,根據相應的配置創建連接並放置在連接池中,以便需要使用時能從連接池中獲 取,這樣就可以避免連接隨意的建立、關閉造成的開銷。

1.2 連接池的管理

連接池管理策略是連接池機制的核心。當連接池建立後,如何對連接池中的 連接進行管理,解決好連接池內連接的分配和釋放,對系統的性能有很大的影響 。連接的合理分配、釋放可提高連接的復用,降低了系統建立新連接的開銷,同 時也加速了用戶的訪問速度。下面介紹連接池中連接的分配、釋放策略。

連接池的分配、釋放策略對於有效復用連接非常重要,我們采用的方法是一 個很有名的設計模式:Reference Counting(引用記數)。該模式在復用資源方 面應用的非常廣泛,把該方法運用到對於連接的分配釋放上,為每一個數據庫連 接,保留一個引用記數,用來記錄該連接的使用者的個數。具體的實現方法是:

當客戶請求數據庫連接時,首先查看連接池中是否有空閒連接(指當前沒有 分配出去的連接)。如果存在空閒連接,則把連接分配給客戶並作相應處理(即 標記該連接為正在使用,引用計數加1)。如果沒有空閒連接,則查看當前所開 的連接數是不是已經達到maxConn(最大連接數),如果沒達到就重新創建一個 連接給請求的客戶;如果達到就按設定的maxWaitTime(最大等待時間)進行等 待,如果等待maxWaitTime後仍沒有空閒連接,就拋出無空閒連接的異常給用戶 。

當客戶釋放數據庫連接時,先判斷該連接的引用次數是否超過了規定值,如 果超過就刪除該連接,並判斷當前連接池內總的連接數是否小於minConn(最小 連接數),若小於就將連接池充滿;如果沒超過就將該連接標記為開放狀態,可 供再次復用。可以看出正是這套策略保證了數據庫連接的有效復用,避免頻繁地 建立、釋放連接所帶來的系統資源開銷。

1.3 連接池的關閉

當應用程序退出時,應關閉連接池,此時應把在連接池建立時向數據庫申請 的連接對象統一歸還給數據庫(即關閉所有數據庫連接),這與連接池的建立正 好是一個相反過程。

1.4 連接池的配置

數據庫連接池中到底要放置多少個連接,才能使系統的性能更佳,用minConn 和maxConn來限制。minConn是當應用啟動的時候連接池所創建的連接數,如果過 大啟動將變慢,但是啟動後響應更快;如果過小啟動加快,但是最初使用的用戶 將因為連接池中沒有足夠的連接不可避免的延緩了執行速度。因此應該在開發的 過程中設定較小minConn,而在實際應用的中設定較大minConn。maxConn是連接 池中的最大連接數,可以通過反復試驗來確定此飽和點。為此在連接池類 ConnectionPool中加入兩個方法getActiveSize()和getOpenSize(), ActiveSize 表示某一時間有多少連接正被使用,OpenSize表示連接池中有多少 連接被打開,反映了連接池使用的峰值。將這兩個值在日志信息中反應出來, minConn的值應該小於平均ActiveSize,而maxConn的值應該在activeSize和 OpenSize之間。

2、連接池的關鍵技術

2.1 事務處理

前面討論的是關於使用數據庫連接進行普通的數據庫訪問。對於事務處理, 情況就變得比較復雜。因為事務本身要求原則性的保證,此時就要求對於數據庫 的操作符合"All-All-Nothing"原則,即要麼全部完成,要麼什麼都不做。如果 簡單的采用上述的連接復用的策略,就會發生問題,因為沒有辦法控制屬於同一 個事務的多個數據庫操作方法的動作,可能這些數據庫操作是在多個連接上進行 的,並且這些連接可能被其他非事務方法復用。Connection本身具有提供了對於 事務的支持,可以通過設置Connection的AutoCommit屬性為false,顯式的調用 commit或rollback方法來實現。但是要安全、高效的進行連接復用,就必須提供 相應的事務支持機制。方法是:采用顯式的事務支撐方法,每一個事務獨占一個 連接。這種方法可以大大降低對於事務處理的復雜性,並且又不會妨礙連接的復 用。

連接管理服務提供了顯式的事務開始、結束(commit或rollback)聲明,以 及一個事務注冊表,用於登記事務發起者和事務使用的連接的對應關系,通過該 表,使用事務的部分和連接管理部分就隔離開,因為該表是在運行時根據實際的 調用情況動態生成的。事務使用的連接在該事務運行中不能被復用。在實現中, 用戶標識是通過使用者所在的線程來標識的。後面的所有對於數據庫的訪問都是 通過查找該注冊表,使用已經分配的連接來完成的。當事務結束時,從注冊表中 刪除相應表項。

2.2 封裝

從上面的論述可以看出,普通的數據庫方法和事務方法對於連接的使用(分 配、釋放)是不同的,為了便於使用,對外提供一致的操作接口,我們對連接進 行了封裝:普通連接和事務連接,並利用了Java中的強大的面向對象特性:多態 。普通連接和事務連接均實現了一個DbConnection接口,對於接口中定義的方法 ,分別根據自己的特點作了不同的實現,這樣在對於連接的處理上就非常的一致 了。

2.3 並發

為了使連接管理服務有更大的通用性,我們必須要考慮到多線程環境,即並 發問題。在一個多線程的環境下,必須要保證連接管理自身數據的一致性和連接 內部數據的一致性,在這方面Java提供很好的支持(synchronized關鍵字),這 樣就很容易使連接管理成為線程安全的。

2.4 多數據庫服務器

在實際應用中,應用程序常常需要訪問多個不同的數據庫。如何通過同一個 連接池訪問不同的數據庫,是應用程序需要解決的一個核心問題。下面介紹一種 解決的途徑:

首先,定義一個數據庫連接池參數的類,定義了數據庫的JDBC驅動程序類名 ,連接的URL以及用戶名口令等等一些信息,該類是用於初始化連接池的參數:

public class ConnectionParam implements Serializable{
  //各初始化參數的定義
}

其次是連接池的工廠類ConnectionFactory,通過該類將一個連接池對象與一 個名稱對應起來,使用者通過該名稱就可以獲取指定的連接池對象,實現的主要 代碼如下:

public class ConnectionFactory{
  static Hashtable connectionPools = //用來保存數據源名和連接池對象 的關系
  public static DataSource lookup(String dataSourceName) throws
  NameNotFoundException{
   //查找名字為dataSourceName的數據源
  }
  public static DataSource bind(String name, ConnectionParam param)
  throws Exception
  //將名字name與使用param初始化的連接池對象綁定
}
public static void unbind(String name) throws NameNotFound
Exception{
  //將與名字name綁定的連接池對象刪除
}

連接池應用的實現

一個完整的連接池應用包括三個部分:DBConnectionPool類,負責從連接池 獲取(或創建)連接、將連接返回給連接池、系統關閉時關閉所有連接釋放所有資 源;DBConnectionManager類,負責裝載和注冊JDBC驅動、根據屬性文件中定義 的屬性創建DBConnectionPool、跟蹤應用程序對連接池的引用等;應用程序對連 接池的使用。

本文實現的數據庫連接池包括一個管理類DBConnectionManager,負責提供與 多個連接池對象(DBConnectionPool類)之間的接口。每一個連接池對象管理一組 封裝過的JDBC連接對象Conn,封裝過的JDBC連接對象Conn可以被任意數量的 Model層的組件共享。

類Conn 的設計很簡單,如下所示:

Class Conn {
  Private java. sgl .Connection con; //數據庫連接對象
  Public Boolean inUse ; //是否被使用
  Public long lastAccess; //最近一次釋放該連接的時間
  Public int useCount; // 被使用次數
}

下面是實現連接池的主要代碼:

// 初始化數據庫連接池
public static synchronized void FastInitPool()
throws Exception {
  try { Class.forName(driver);
   for (int i=0; i<size; i++) {
    Connection con = createConnection();
    if (con!=null) addConnection(con);
   } } }
// 向連接池對象中添加數據庫連接
private static void addConnection(Connection con) {
  if (pool=null||pool1=null) {
   pool=new Vector(size);
   pool1=new Vector(size); }
  pool.addElement(con);
  pool1.addElement("false"); }
// 獲取數據庫連接
public static synchronized Connection getConn()
throws Exception {
  Connection conn = null;
  try { if (driver = null)
   FastInitPool();
   // 獲得一個可用的(空閒的)連接
  .for (int i = 0; i < pool.size(); i++) {
   conn = (Connection)pool.elementAt(i);
   if (pool1.elementAt(i)=="false") {
    pool1.set(i,"true");
    //System.out.println("從連接池中獲取第"+(i+1)+"個空閒連 接");
    return conn;
   }
  }
  //如果沒有可用連接,且已有連接數小於最大連接數限制,則創建並增加一 個新連接到連接池
  conn = createConnection();
  pool.addElement(conn);
  pool1.addElement("true");
  // System.out.println(" 所有連接都在使用,在連接池中再創建一個新連接 ");
}
catch (Exception e) {
  System.err.println(e.getMessage());
  throw new Exception(e.getMessage());
}
return conn; //返回一個有效的新連接
}
public Connection getConnection(String strDriver, String strUrl, String strUserName, String strPassWord)
throws SQLException{
  try{ Class.forName(strDriver);
   conn = DriverManager.getConnection(strUrl, strUserName, strPassWord); }
  return conn; }

結束語

當前Web應用程序廣泛采用B/S結構,其並發性決定了多用戶同時訪問數據庫 的問題。本文闡述的基於JDBC的數據庫連接池技術已成功應用於基於Web的高職 教學系統開發中,並建立了數據庫連接池實例來說明和證實連接池的訪問方法。 只有充分運用連接池訪問技術,才能提高數據庫的訪問效率,改善Web應用,從 而減少系統開銷,大大提高整個Web應用系統的運行效率。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved