在JDBC2.0或JDBC3.0中,所有的資料庫驅動程式提供商必須提供一個實現了DataSource介面的類,要使用資料來源必須首先在JNDI中註冊該資料來源物件。
如果在JNDI中註冊了資料來源物件,將會比起使用DriverManager來具有兩個方面的優勢:
首先,程式不需要像使用DriverManager一樣對載入的資料庫驅動程式資訊進行硬編碼,程式設計師可以選擇先在JNDI中註冊這個資料來源物件,然後在 程式中使用一個邏輯名稱來引用它,JNDI會自動根據你給出的名稱找到與這個名稱繫結的DataSource物件。然後就可以使用這個 DataSource物件來建立和具體資料庫的連線了。
其次,使用實現了DataSource介面的類所具有的第二個優勢體現在連線池和分散式事務上。連線池透過對連線的複用而不是新建一個物理連線來顯著地提高程式的效率。從而適用於任務繁忙、負擔繁重的企業級分散式事務。
資料庫連線池的基本原理
傳統的資料庫連線方式(指透過DriverManager和基本實現DataSource進行連線)中,一個數據庫連線物件均對應一個物理資料庫連線,數 據庫連線的建立以及關閉對系統而言是耗費系統資源的操作,在多層結構的應用程式環境中這種耗費資源的動作對系統的效能影響尤為明顯。
在多層結構的應用程式中透過連線池(connection pooling)技術可以使系統的效能明顯得到提到,連線池意味著當應用程式需要呼叫一個數據庫連線的時,資料庫相關的介面透過返回一個透過重用資料庫連 接來代替重新建立一個數據庫連線。透過這種方式,應用程式可以減少對資料庫連線操作,尤其在多層環境中多個客戶端可以透過共享少量的物理資料庫連線來滿足 系統需求。透過連線池技術Java應用程式不僅可以提高系統性能同時也為系統提高了可測量性。
資料庫連線池是執行在後臺的而且應用程式的編碼沒有任何的影響。此中狀況存在的前提是應用程式必須透過DataSource物件(一個實現 javax.sql.DataSource介面的例項)的方式代替原有透過DriverManager類來獲得資料庫連線的方式。一個實現 javax.sql.DataSource介面的類可以支援也可以不支援資料庫連線池,但是兩者獲得資料庫連線的程式碼基本是相同的。
一個DataSource物件通常註冊在JNDI命名服務上,應用程式可以透過標準的方式獲得到註冊在JNDI服務上的DataSource物件。 程式碼如下:
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("jdbc/openbase");
如果當前DataSource不支援資料庫連線池,應用程式將獲得一個和物理資料庫連線對應的Connection物件。而如果當前的 DataSource物件支援資料庫連線池,應用程式自動獲得重用的資料庫連線而不用建立新的資料庫連線。重用的資料庫連線和新建立連線的資料庫連線使用 上沒有任何不同。應用程式可以透過重用的連線正常的訪問資料庫,進行訪問資料的操作,完成操作後應顯式的呼叫close()關閉資料庫連線。
Connection con = ds.getConnection("User", "Pwd");
相關資料庫的操作;
con.close();
當關閉資料連線後,當前使用的資料庫連線將不會被物理關閉,而是放回到資料庫連線池中進行重用。
JDBC3.0規範中資料庫連線池框架
JDBC3.0規範中透過提供了一個支援資料庫連線池的框架,這個框架僅僅規定了如何支援連線池的實現,而連線池的具體實現JDBC 3.0規範並沒有做相關的規定。透過這個框架可以讓不同角色的開發人員共同實現資料庫連線池。
透過JDBC3.0規範可以知道具體資料庫連線池的實現可以分為JDBC Driver級和Application Server級。在JDBC Driver級的實現中任何相關的工作均由特定資料庫廠商的JDBC Drvier的開發人員來具體實現,即JDBC Driver既需要提供對資料庫連線池的支援同時也必須對資料庫連線池進行具體實現。而在Application Server級中資料庫連線池的實現中特定資料庫廠商的JDBC Driver開發人員和Application Server開發人員來共同實現資料庫連線池的實現(但是現在大多數Application Server廠商實現的連線池的機制和規範中提到有差異),其中特定資料庫廠商的JDBC Driver提供資料庫連線池的支援而特定的Application Server廠商提供資料庫連線池的具體實現。
JDBC3.0規範規定了如下的類和介面來支援資料庫連線池的實現。
javax.sql.ConnectionEvent
javax.sql.ConnectionPoolDataSource
javax.sql.PooledConnection
javax.sql.ConnectionEventListener
其中除javax.sql.ConnectionEvent是類,其它的均為介面。
C:/1.jpg
screen.width-333)this.width=screen.width-333;" src="/Develop/ArticleImages/19/19446/CSDN_Dev_Image_2003-7-41948411.jpg">
JDBC3.0連線池框架的關係圖
透過此圖可以大概的瞭解相關介面在一個典型的三層環境中應用程式的位置。
資料庫連線池實現層次中,由特定資料庫廠商的JDBC Driver開發人員提供連線池支援,而特定Application Server提供連線池實現的情況比較複雜,其它的實現層次均可視為其簡化情況的一種。下面將針對這種情況進行說明。
在這個框架主要有兩個使用者角色存在,它們分別是:
特定資料庫廠商的JDBC Driver開發人員,之後將簡稱為Driver Vendor
特定Application Server中連線池開發人員,之後將簡稱為Pooling Vendor
C:/2.bmp
screen.width-333)this.width=screen.width-333;" src="/Develop/ArticleImages/19/19446/CSDN_Dev_Image_2003-7-41948413.gif">
JDBC3.0規範中在上述情況下各個介面和類之間的UML圖
下面對幾個關鍵模組進行詳細的說明:
Driver Vendor DataSource:
Driver Vendor必須提供一個ConnectionPoolDataSource 介面的具體實現,透過這個介面Pooling Vendor可以得到一個PooledConnection物件,從而使第三方實現的連線池可以使用特定資料庫廠商得到JDBC Driver產生的資料庫連線。在這裡ConnectionPoolDataSource介面扮演的角色可以視為產生PooledConnection 物件的工廠。
Driver Vendor PooledConnection:
Driver Vendor必須提供標準PooledConnection 介面實現的類,這個介面允許Pooling Vendor在JDBC Driver提供連線池支援的基礎上實現連線池。一個具體PooledConnection物件代表了一個物理的資料庫連線;由 PooledConnection物件建立Connection物件僅僅只是一個指向PooledConnetion物件的控制代碼。在JDBC 3.0連線池實現框架中PooledConnection物件扮演的角色可以視為產生Connection物件的工廠。
Pooling Vendor DataSource:
Pooling Vendor必須實現DataSource介面,這個介面是和連線池實現模組進行互動的入口點。ConnectionPoolDataSource根據需要建立PooledConnection物件。
Pooling Vendor Connection Cache:
此模組是Pooling Vendor對連線池的具體實現。JDBC 3.0 規範沒有規定在DataSource物件和資料庫連線池實現之間的需要實現的介面,所以它們之間的互動由Pooling Vendor自己定義。一般而言,一個數據庫連線池的具體實現包含了一個或若干個具體的類,但是在連線池實現模組中必須包含一個類實現標準 ConnectionEventListener介面。當一個PooledConnectiond物件被關閉或者出現異常的時 候,PooledConnection物件將會向ConnectionEventListener介面傳送ConnectionEvent物件,連線池實 現模組將會根據返回的ConnectionEvent物件對PooledConnection進行關閉或者重用操作。
ConnectionEvent:
實現連線池時,當應用程式呼叫Connection.close()試圖去關閉資料庫連線時,這時需要有一個通告給連線池實現模組,通告對當前的資料 庫物理連線(PooledConnection 物件)進行重用。為了使連線池實現模組能得到這種"通告",連線池實現模組必須實現ConnectionEventListener介面,而且同時需要注 冊成為PooledConnection物件的監聽者。連線池實現模組透過 PooledConnection.addConnectionEventListener()方法註冊自己成為一個監聽者。
在典型三層環境中具體呼叫流程:
當應用程式透過呼叫DataSource.getConnection()得到一個數據庫連線。
Pooling Vendor實現的DataSource物件在連線池中進行查詢看當前是否有有效的PooledConnection物件,如果連線池中有可用的PooledConnection,則進行檢查,如果當前的PooledConnection可用則使用。
如果如果連線池中沒有可用的PooledConnection物件,或者當前的PooledConnection物件不正確,那麼Pooling Vendor呼叫ConnectionPoolDataSource.getPooledConnection類建立一個新的 PooledConnection物件,這時由Driver Vendor實現的ConnectionPoolDataSource將會建立一個滿足要求新的PooledConnection物件,並將其返回給連線 池實現模組進行管理。
然後,Pooling Vendor會呼叫PooledConnection.getConnection()獲得一個邏輯的Connection物件,這個邏輯的 Connection物件將會象正常的Connection物件返回給應用程式。這個邏輯Connection物件實際上是連線池中 PooledConnection物件的一個控制代碼,當連線池有效時,應用程式呼叫DataSource.getConnection()就會得到這個句 柄。簡而言之,應用程式此時使用的Connection物件僅僅是其建立者PooledConnection物件的控制代碼而已。
連線池實現模組呼叫PooledConnection.addConnectionEventListener()將自己註冊成為一個PooledConnection物件的監聽者,當資料庫連線需要重用或者關閉的時候連線池實現模組可以得到通告。
當應用程式透過呼叫Connection.close()來關閉資料庫連線,這時一個ConnectionEvent物件被建立並被返回到連線池實現 模組,連線池實現模組接受到此通告後,將PooledConnection物件返回到池中進行重用。這些過程中其它角色都不能訪問 PooledConnection.close()方法,能訪問這個方法的只有Pooling Vendor,它們使用這個方法對連線池中的物件進行操作,透過PooledConnection.close()方法可以關閉物理資料庫連線。
在JDBC2.0或JDBC3.0中,所有的資料庫驅動程式提供商必須提供一個實現了DataSource介面的類,要使用資料來源必須首先在JNDI中註冊該資料來源物件。
如果在JNDI中註冊了資料來源物件,將會比起使用DriverManager來具有兩個方面的優勢:
首先,程式不需要像使用DriverManager一樣對載入的資料庫驅動程式資訊進行硬編碼,程式設計師可以選擇先在JNDI中註冊這個資料來源物件,然後在 程式中使用一個邏輯名稱來引用它,JNDI會自動根據你給出的名稱找到與這個名稱繫結的DataSource物件。然後就可以使用這個 DataSource物件來建立和具體資料庫的連線了。
其次,使用實現了DataSource介面的類所具有的第二個優勢體現在連線池和分散式事務上。連線池透過對連線的複用而不是新建一個物理連線來顯著地提高程式的效率。從而適用於任務繁忙、負擔繁重的企業級分散式事務。
資料庫連線池的基本原理
傳統的資料庫連線方式(指透過DriverManager和基本實現DataSource進行連線)中,一個數據庫連線物件均對應一個物理資料庫連線,數 據庫連線的建立以及關閉對系統而言是耗費系統資源的操作,在多層結構的應用程式環境中這種耗費資源的動作對系統的效能影響尤為明顯。
在多層結構的應用程式中透過連線池(connection pooling)技術可以使系統的效能明顯得到提到,連線池意味著當應用程式需要呼叫一個數據庫連線的時,資料庫相關的介面透過返回一個透過重用資料庫連 接來代替重新建立一個數據庫連線。透過這種方式,應用程式可以減少對資料庫連線操作,尤其在多層環境中多個客戶端可以透過共享少量的物理資料庫連線來滿足 系統需求。透過連線池技術Java應用程式不僅可以提高系統性能同時也為系統提高了可測量性。
資料庫連線池是執行在後臺的而且應用程式的編碼沒有任何的影響。此中狀況存在的前提是應用程式必須透過DataSource物件(一個實現 javax.sql.DataSource介面的例項)的方式代替原有透過DriverManager類來獲得資料庫連線的方式。一個實現 javax.sql.DataSource介面的類可以支援也可以不支援資料庫連線池,但是兩者獲得資料庫連線的程式碼基本是相同的。
一個DataSource物件通常註冊在JNDI命名服務上,應用程式可以透過標準的方式獲得到註冊在JNDI服務上的DataSource物件。 程式碼如下:
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("jdbc/openbase");
如果當前DataSource不支援資料庫連線池,應用程式將獲得一個和物理資料庫連線對應的Connection物件。而如果當前的 DataSource物件支援資料庫連線池,應用程式自動獲得重用的資料庫連線而不用建立新的資料庫連線。重用的資料庫連線和新建立連線的資料庫連線使用 上沒有任何不同。應用程式可以透過重用的連線正常的訪問資料庫,進行訪問資料的操作,完成操作後應顯式的呼叫close()關閉資料庫連線。
Connection con = ds.getConnection("User", "Pwd");
相關資料庫的操作;
con.close();
當關閉資料連線後,當前使用的資料庫連線將不會被物理關閉,而是放回到資料庫連線池中進行重用。
JDBC3.0規範中資料庫連線池框架
JDBC3.0規範中透過提供了一個支援資料庫連線池的框架,這個框架僅僅規定了如何支援連線池的實現,而連線池的具體實現JDBC 3.0規範並沒有做相關的規定。透過這個框架可以讓不同角色的開發人員共同實現資料庫連線池。
透過JDBC3.0規範可以知道具體資料庫連線池的實現可以分為JDBC Driver級和Application Server級。在JDBC Driver級的實現中任何相關的工作均由特定資料庫廠商的JDBC Drvier的開發人員來具體實現,即JDBC Driver既需要提供對資料庫連線池的支援同時也必須對資料庫連線池進行具體實現。而在Application Server級中資料庫連線池的實現中特定資料庫廠商的JDBC Driver開發人員和Application Server開發人員來共同實現資料庫連線池的實現(但是現在大多數Application Server廠商實現的連線池的機制和規範中提到有差異),其中特定資料庫廠商的JDBC Driver提供資料庫連線池的支援而特定的Application Server廠商提供資料庫連線池的具體實現。
JDBC3.0規範規定了如下的類和介面來支援資料庫連線池的實現。
javax.sql.ConnectionEvent
javax.sql.ConnectionPoolDataSource
javax.sql.PooledConnection
javax.sql.ConnectionEventListener
其中除javax.sql.ConnectionEvent是類,其它的均為介面。
C:/1.jpg
screen.width-333)this.width=screen.width-333;" src="/Develop/ArticleImages/19/19446/CSDN_Dev_Image_2003-7-41948411.jpg">
JDBC3.0連線池框架的關係圖
透過此圖可以大概的瞭解相關介面在一個典型的三層環境中應用程式的位置。
資料庫連線池實現層次中,由特定資料庫廠商的JDBC Driver開發人員提供連線池支援,而特定Application Server提供連線池實現的情況比較複雜,其它的實現層次均可視為其簡化情況的一種。下面將針對這種情況進行說明。
在這個框架主要有兩個使用者角色存在,它們分別是:
特定資料庫廠商的JDBC Driver開發人員,之後將簡稱為Driver Vendor
特定Application Server中連線池開發人員,之後將簡稱為Pooling Vendor
C:/2.bmp
screen.width-333)this.width=screen.width-333;" src="/Develop/ArticleImages/19/19446/CSDN_Dev_Image_2003-7-41948413.gif">
JDBC3.0規範中在上述情況下各個介面和類之間的UML圖
下面對幾個關鍵模組進行詳細的說明:
Driver Vendor DataSource:
Driver Vendor必須提供一個ConnectionPoolDataSource 介面的具體實現,透過這個介面Pooling Vendor可以得到一個PooledConnection物件,從而使第三方實現的連線池可以使用特定資料庫廠商得到JDBC Driver產生的資料庫連線。在這裡ConnectionPoolDataSource介面扮演的角色可以視為產生PooledConnection 物件的工廠。
Driver Vendor PooledConnection:
Driver Vendor必須提供標準PooledConnection 介面實現的類,這個介面允許Pooling Vendor在JDBC Driver提供連線池支援的基礎上實現連線池。一個具體PooledConnection物件代表了一個物理的資料庫連線;由 PooledConnection物件建立Connection物件僅僅只是一個指向PooledConnetion物件的控制代碼。在JDBC 3.0連線池實現框架中PooledConnection物件扮演的角色可以視為產生Connection物件的工廠。
Pooling Vendor DataSource:
Pooling Vendor必須實現DataSource介面,這個介面是和連線池實現模組進行互動的入口點。ConnectionPoolDataSource根據需要建立PooledConnection物件。
Pooling Vendor Connection Cache:
此模組是Pooling Vendor對連線池的具體實現。JDBC 3.0 規範沒有規定在DataSource物件和資料庫連線池實現之間的需要實現的介面,所以它們之間的互動由Pooling Vendor自己定義。一般而言,一個數據庫連線池的具體實現包含了一個或若干個具體的類,但是在連線池實現模組中必須包含一個類實現標準 ConnectionEventListener介面。當一個PooledConnectiond物件被關閉或者出現異常的時 候,PooledConnection物件將會向ConnectionEventListener介面傳送ConnectionEvent物件,連線池實 現模組將會根據返回的ConnectionEvent物件對PooledConnection進行關閉或者重用操作。
ConnectionEvent:
實現連線池時,當應用程式呼叫Connection.close()試圖去關閉資料庫連線時,這時需要有一個通告給連線池實現模組,通告對當前的資料 庫物理連線(PooledConnection 物件)進行重用。為了使連線池實現模組能得到這種"通告",連線池實現模組必須實現ConnectionEventListener介面,而且同時需要注 冊成為PooledConnection物件的監聽者。連線池實現模組透過 PooledConnection.addConnectionEventListener()方法註冊自己成為一個監聽者。
在典型三層環境中具體呼叫流程:
當應用程式透過呼叫DataSource.getConnection()得到一個數據庫連線。
Pooling Vendor實現的DataSource物件在連線池中進行查詢看當前是否有有效的PooledConnection物件,如果連線池中有可用的PooledConnection,則進行檢查,如果當前的PooledConnection可用則使用。
如果如果連線池中沒有可用的PooledConnection物件,或者當前的PooledConnection物件不正確,那麼Pooling Vendor呼叫ConnectionPoolDataSource.getPooledConnection類建立一個新的 PooledConnection物件,這時由Driver Vendor實現的ConnectionPoolDataSource將會建立一個滿足要求新的PooledConnection物件,並將其返回給連線 池實現模組進行管理。
然後,Pooling Vendor會呼叫PooledConnection.getConnection()獲得一個邏輯的Connection物件,這個邏輯的 Connection物件將會象正常的Connection物件返回給應用程式。這個邏輯Connection物件實際上是連線池中 PooledConnection物件的一個控制代碼,當連線池有效時,應用程式呼叫DataSource.getConnection()就會得到這個句 柄。簡而言之,應用程式此時使用的Connection物件僅僅是其建立者PooledConnection物件的控制代碼而已。
連線池實現模組呼叫PooledConnection.addConnectionEventListener()將自己註冊成為一個PooledConnection物件的監聽者,當資料庫連線需要重用或者關閉的時候連線池實現模組可以得到通告。
當應用程式透過呼叫Connection.close()來關閉資料庫連線,這時一個ConnectionEvent物件被建立並被返回到連線池實現 模組,連線池實現模組接受到此通告後,將PooledConnection物件返回到池中進行重用。這些過程中其它角色都不能訪問 PooledConnection.close()方法,能訪問這個方法的只有Pooling Vendor,它們使用這個方法對連線池中的物件進行操作,透過PooledConnection.close()方法可以關閉物理資料庫連線。