一個不錯的JDBC連線池教程(帶具體例子)
1.前言
資料庫應用,在許多軟體系統中經常用到,是開發中大型系統不可缺少的輔助。但如果對資料庫資源沒有很好地管理(如:沒有及時回收資料庫的遊標(ResultSet)、Statement、連線 (Connection)等資源),往往會直接導致系統的穩定。這類不穩定因素,不單單由資料庫或者系統本身一方引起,只有系統正式使用後,隨著流量、使用者的增加,才會逐步顯露。
在b基於Java開發的系統中,JDBC是程式設計師和資料庫打交道的主要途徑,提供了完備的資料庫操作方法介面。但考慮到規範的適用性,JDBC只提供了最直接的資料庫操作規範,對資料庫資源管理,如:對物理連線的管理及緩衝,期望第三方應用伺服器(Application Server)的提供。
本文,以JDBC規範為基礎,介紹相關的資料庫連線池機制,並就如果以簡單的方式,實現有效地管理資料庫資源介紹相關實現技術。
2.連線池技術背景
2.1JDBC
JDBC是一個規範,遵循JDBC介面規範,各個資料庫廠家各自實現自己的驅動程式(Driver),如下圖所示:
應用在獲取資料庫連線時,需要以URL的方式指定是那種型別的Driver,在獲得特定的連線後,可按照固定的介面操作不同型別的資料庫,如: 分別獲取Statement、執行SQL獲得ResultSet等,如下面的例子 :
import java.sql.*;
…
..DriverManager.registerDriver(
new oracle.jdbc.
driver.OracleDriver());
Connection dbConn = DriverManager.getConnection
(“jdbc:oracle:thin:@127.0.0.1:1521:
oracle”,“username”, “password” );
Statement st = dbConn.createStatement();
ResultSet rs = st.executeQuery(
“select * from demo_table” );
…
some data source operation in herers.close();
st.close();dbConn.close();
在完成資料操作後,還一定要關閉所有涉及到的資料庫資源。這雖然對應用程式的邏輯沒有任何影響,但是關鍵的操作。上面是個簡單的例子,如果攙和眾多的if-else、exception,資源的管理也難免百密一疏。如同C中的記憶體洩漏問題,Java系統也同樣會面臨崩潰的惡運。所以資料庫資源的管理依賴於應用系統本身,是不安全、不穩定的一種隱患。
2.2JDBC連線池
在標準JDBC對應用的介面中,並沒有提供資源的管理方法。所以,預設的資源管理由應用自己負責。雖然在JDBC規範中,多次提及資源的關閉/回收及其他的合理運用。但最穩妥的方式,還是為應用提供有效的管理手段。所以,JDBC為第三方應用伺服器(Application Server)提供了一個由資料庫廠家實現的管理標準介面:連線緩衝(connection pooling)。引入了連線池( Connection Pool )的概念 ,也就是以緩衝池的機制管理資料庫的資源。
JDBC最常用的資源有三類:
-Connection: 資料庫連線。
-Statement: 會話宣告。
-ResultSet: 結果集遊標。
分別存在以下的關係 :
這是一種 ‘爺-父-子’ 的關係,對Connection的管理,就是對資料庫資源的管理。舉個例子: 如果想確定某個資料庫連線(Connection)是否超時,則需要確定其(所有的)子Statement是否超時,同樣,需要確定所有相關的ResultSet是否超時;在關閉Connection前,需要關閉所有相關的Statement和ResultSet。
因此,連線池(Connection Pool)所起到的作用,不僅僅簡單地管理Connection,還涉及到 Statement和ResultSet。
2.3連線池(ConnectionPool)與資源管理
ConnectionPool以緩衝池的機制,在一定數量上限範圍內,控制管理Connection,Statement和ResultSet。任何資料庫的資源是有限的,如果被耗盡,則無法獲得更多的資料服務。
在大多數情況下,資源的耗盡不是由於應用的正常負載過高,而是程式原因。
在實際工作中,資料資源往往是瓶頸資源,不同的應用都會訪問同一資料來源。其中某個應用耗盡了資料庫資源後,意味其他的應用也無法正常執行。因此,ConnectionPool的第一個任務是限制:每個應用或系統可以擁有的最大資源。也就是確定連線池的大小(PoolSize)。
ConnectionPool的第二個任務:在連線池的大小(PoolSize)範圍內,最大限度地使用資源,縮短資料庫訪問的使用週期。許多資料庫中,連線(Connection)並不是資源的最小單元,控制Statement資源比Connection更重要。以Oracle為例:
每申請一個連線(Connection)會在物理網路(如 TCP/IP網路)上建立一個用於通訊的連線,在此連線上還可以申請一定數量的Statement。同一連線可提供的活躍Statement數量可以達到幾百。 在節約網路資源的同時,縮短了每次會話週期(物理連線的建立是個費時的操作)。但在一般的應用中,多數按照2.1範例操作,這樣有10個程式呼叫,則會產生10次物理連線,每個Statement單獨佔用一個物理連線,這是極大的資源浪費。 ConnectionPool可以解決這個問題,讓幾十、幾百個Statement只佔用同一個物理連線, 發揮資料庫原有的優點。
通過ConnectionPool對資源的有效管理,應用可以獲得的Statement總數到達 :
(併發物理連線數) x (每個連線可提供的Statement數量)
例如某種資料庫可同時建立的物理連線數為 200個,每個連線可同時提供250個Statement,那麼ConnectionPool最終為應用提供的併發Statement總數為: 200 x 250 = 50,000個。這是個併發數字,很少有系統會突破這個量級。所以在本節的開始,指出資源的耗盡與應用程式直接管理有關。
對資源的優化管理,很大程度上依靠資料庫自身的JDBC Driver是否具備。有些資料庫的JDBC Driver並不支援Connection與Statement之間的邏輯連線功能,如SQLServer,我們只能等待她自身的更新版本了。
對資源的申請、釋放、回收、共享和同步,這些管理是複雜精密的。所以,ConnectionPool另一個功能就是,封裝這些操作,為應用提供簡單的,甚至是不改變應用風格的呼叫介面。
3.簡單JDBC連線池的實現
根據第二章中原理機制,Snap-ConnectionPool(一種簡單快速的連線池工具)按照部分的JDBC規範,實現了連線池所具備的對資料庫資源有效管理功能。
3.1體系描述
在JDBC規範中,應用通過驅動介面(Driver Interface)直接方法資料庫的資源。為了有效、合理地管理資源,在應用與JDBC Driver之間,增加了連線池: Snap-ConnectionPool。並且通過物件導向的機制,使連線池的大部分操作是透明的。參見下圖,Snap-ConnectionPool的體系:
圖中所示,通過實現JDBC的部分資源物件介面( Connection, Statement, ResultSet ),在 Snap-ConnectionPool內部分別產生三種邏輯資源物件: PooledConnection, PooledStatement和 PooledResultSet。它們也是連線池主要的管理操作物件,並且繼承了JDBC中相應的從屬關係。這樣的體系有以下幾個特點:
-透明性。在不改變應用原有的使用JDBC驅動介面的前提下,提供資源管理的服務。應用系統,如同原有的 JDBC,使用連線池提供的邏輯物件資源。簡化了應用程式的連線池改造。
-資源封裝。複雜的資源管理被封裝在 Snap-ConnectionPool內部,不需要應用系統過多的干涉。管理操作的可靠性、安全性由連線池保證。應用的干涉(如:主動關閉資源),只起到優化系統效能的作用,遺漏操作不會帶來負面影響。
-資源合理應用。按照JDBC中資源的從屬關係,Snap-ConnectionPool不僅對Connection進行緩衝處理,對Statement也有相應的機制處理。在2.3已描述,合理運用Connection和Statement之間的關係,可以更大限度地使用資源。所以,Snap-ConnectionPool封裝了Connection資源,通過內部管理PooledConnection,為應用系統提供更多的Statement資源。
-資源連鎖管理。Snap-ConnectionPool包含的三種邏輯物件,繼承了JDBC中相應物件之間的從屬關係。在內部管理中,也依照從屬關係進行連鎖管理。例如:判斷一個Connection是否超時,需要根據所包含的Statement是否活躍;判斷Statement也要根據ResultSet的活躍程度。
3.2連線池集中管理ConnectionManager
ConnectionPool是Snap-ConnectionPool的連線池物件。在Snap-ConnectionPool內部,可以指定多個不同的連線池(ConnectionPool)為應用服務。ConnectionManager管理所有的連線池,每個連線池以不同的名稱區別。通過配置檔案適應不同的資料庫種類。如下圖所示:
通過ConnectionManager,可以同時管理多個不同的連線池,提供通一的管理介面。在應用系統中通過ConnectionManager和相關的配置檔案,可以將凌亂散落在各自應用程式中的資料庫配置資訊(包括:資料庫名、使用者、密碼等資訊),集中在一個檔案中。便於系統的維護工作。
3.3連線池使用範例
對2.1的標準JDBC的使用範例,改為使用連線池,結果如下:
import java.sql.*;
import net.snapbug.util.dbtool.*;
…
..ConnectionPool dbConn = ConnectionManager
.getConnectionPool("testOracle" );
Statement st = dbConn.createStatement();
ResultSet rs = st.executeQuery(
“select * from demo_table” );
…
some data source operation
in herers.close();st.close();
在例子中,Snap-ConnectionPool封裝了應用對Connection的管理。只要改變JDBC獲取Connection的方法,為獲取連線池(ConnectionPool)(粗體部分),其他的資料操作都可以不做修改。按照這樣的方式,Snap-ConnectionPool可幫助應用有效地管理資料庫資源。如果應用忽視了最後資源的釋放: rs.close() 和 st.close(),連線池會通過超時(time-out)機制,自動回收。
4.小結
無論是Snap-ConnectionPool還是其他的資料庫連線池,都應當具備一下基本功能:
-對源資料庫資源的保護
-充分利用發揮資料庫的有效資源
-簡化應用的資料庫介面,封閉資源管理。
-對應用遺留資源的自動回收和整理,提高資源的再次利用率。
在這個前提下,應用程式才能投入更多的精力於各自的業務邏輯中。資料庫資源也不再成為系統的瓶頸。
注: 在網站 www.snapbug.net可免費下載Snap-ConnectionPool及更詳細的文件。
資料庫應用,在許多軟體系統中經常用到,是開發中大型系統不可缺少的輔助。但如果對資料庫資源沒有很好地管理(如:沒有及時回收資料庫的遊標(ResultSet)、Statement、連線 (Connection)等資源),往往會直接導致系統的穩定。這類不穩定因素,不單單由資料庫或者系統本身一方引起,只有系統正式使用後,隨著流量、使用者的增加,才會逐步顯露。
在b基於Java開發的系統中,JDBC是程式設計師和資料庫打交道的主要途徑,提供了完備的資料庫操作方法介面。但考慮到規範的適用性,JDBC只提供了最直接的資料庫操作規範,對資料庫資源管理,如:對物理連線的管理及緩衝,期望第三方應用伺服器(Application Server)的提供。
本文,以JDBC規範為基礎,介紹相關的資料庫連線池機制,並就如果以簡單的方式,實現有效地管理資料庫資源介紹相關實現技術。
2.連線池技術背景
2.1JDBC
JDBC是一個規範,遵循JDBC介面規範,各個資料庫廠家各自實現自己的驅動程式(Driver),如下圖所示:
應用在獲取資料庫連線時,需要以URL的方式指定是那種型別的Driver,在獲得特定的連線後,可按照固定的介面操作不同型別的資料庫,如: 分別獲取Statement、執行SQL獲得ResultSet等,如下面的例子 :
import java.sql.*;
…
..DriverManager.registerDriver(
new oracle.jdbc.
driver.OracleDriver());
Connection dbConn = DriverManager.getConnection
(“jdbc:oracle:thin:@127.0.0.1:1521:
oracle”,“username”, “password” );
Statement st = dbConn.createStatement();
ResultSet rs = st.executeQuery(
“select * from demo_table” );
…
some data source operation in herers.close();
st.close();dbConn.close();
在完成資料操作後,還一定要關閉所有涉及到的資料庫資源。這雖然對應用程式的邏輯沒有任何影響,但是關鍵的操作。上面是個簡單的例子,如果攙和眾多的if-else、exception,資源的管理也難免百密一疏。如同C中的記憶體洩漏問題,Java系統也同樣會面臨崩潰的惡運。所以資料庫資源的管理依賴於應用系統本身,是不安全、不穩定的一種隱患。
2.2JDBC連線池
在標準JDBC對應用的介面中,並沒有提供資源的管理方法。所以,預設的資源管理由應用自己負責。雖然在JDBC規範中,多次提及資源的關閉/回收及其他的合理運用。但最穩妥的方式,還是為應用提供有效的管理手段。所以,JDBC為第三方應用伺服器(Application Server)提供了一個由資料庫廠家實現的管理標準介面:連線緩衝(connection pooling)。引入了連線池( Connection Pool )的概念 ,也就是以緩衝池的機制管理資料庫的資源。
JDBC最常用的資源有三類:
-Connection: 資料庫連線。
-Statement: 會話宣告。
-ResultSet: 結果集遊標。
分別存在以下的關係 :
這是一種 ‘爺-父-子’ 的關係,對Connection的管理,就是對資料庫資源的管理。舉個例子: 如果想確定某個資料庫連線(Connection)是否超時,則需要確定其(所有的)子Statement是否超時,同樣,需要確定所有相關的ResultSet是否超時;在關閉Connection前,需要關閉所有相關的Statement和ResultSet。
因此,連線池(Connection Pool)所起到的作用,不僅僅簡單地管理Connection,還涉及到 Statement和ResultSet。
2.3連線池(ConnectionPool)與資源管理
ConnectionPool以緩衝池的機制,在一定數量上限範圍內,控制管理Connection,Statement和ResultSet。任何資料庫的資源是有限的,如果被耗盡,則無法獲得更多的資料服務。
在大多數情況下,資源的耗盡不是由於應用的正常負載過高,而是程式原因。
在實際工作中,資料資源往往是瓶頸資源,不同的應用都會訪問同一資料來源。其中某個應用耗盡了資料庫資源後,意味其他的應用也無法正常執行。因此,ConnectionPool的第一個任務是限制:每個應用或系統可以擁有的最大資源。也就是確定連線池的大小(PoolSize)。
ConnectionPool的第二個任務:在連線池的大小(PoolSize)範圍內,最大限度地使用資源,縮短資料庫訪問的使用週期。許多資料庫中,連線(Connection)並不是資源的最小單元,控制Statement資源比Connection更重要。以Oracle為例:
每申請一個連線(Connection)會在物理網路(如 TCP/IP網路)上建立一個用於通訊的連線,在此連線上還可以申請一定數量的Statement。同一連線可提供的活躍Statement數量可以達到幾百。 在節約網路資源的同時,縮短了每次會話週期(物理連線的建立是個費時的操作)。但在一般的應用中,多數按照2.1範例操作,這樣有10個程式呼叫,則會產生10次物理連線,每個Statement單獨佔用一個物理連線,這是極大的資源浪費。 ConnectionPool可以解決這個問題,讓幾十、幾百個Statement只佔用同一個物理連線, 發揮資料庫原有的優點。
通過ConnectionPool對資源的有效管理,應用可以獲得的Statement總數到達 :
(併發物理連線數) x (每個連線可提供的Statement數量)
例如某種資料庫可同時建立的物理連線數為 200個,每個連線可同時提供250個Statement,那麼ConnectionPool最終為應用提供的併發Statement總數為: 200 x 250 = 50,000個。這是個併發數字,很少有系統會突破這個量級。所以在本節的開始,指出資源的耗盡與應用程式直接管理有關。
對資源的優化管理,很大程度上依靠資料庫自身的JDBC Driver是否具備。有些資料庫的JDBC Driver並不支援Connection與Statement之間的邏輯連線功能,如SQLServer,我們只能等待她自身的更新版本了。
對資源的申請、釋放、回收、共享和同步,這些管理是複雜精密的。所以,ConnectionPool另一個功能就是,封裝這些操作,為應用提供簡單的,甚至是不改變應用風格的呼叫介面。
3.簡單JDBC連線池的實現
根據第二章中原理機制,Snap-ConnectionPool(一種簡單快速的連線池工具)按照部分的JDBC規範,實現了連線池所具備的對資料庫資源有效管理功能。
3.1體系描述
在JDBC規範中,應用通過驅動介面(Driver Interface)直接方法資料庫的資源。為了有效、合理地管理資源,在應用與JDBC Driver之間,增加了連線池: Snap-ConnectionPool。並且通過物件導向的機制,使連線池的大部分操作是透明的。參見下圖,Snap-ConnectionPool的體系:
圖中所示,通過實現JDBC的部分資源物件介面( Connection, Statement, ResultSet ),在 Snap-ConnectionPool內部分別產生三種邏輯資源物件: PooledConnection, PooledStatement和 PooledResultSet。它們也是連線池主要的管理操作物件,並且繼承了JDBC中相應的從屬關係。這樣的體系有以下幾個特點:
-透明性。在不改變應用原有的使用JDBC驅動介面的前提下,提供資源管理的服務。應用系統,如同原有的 JDBC,使用連線池提供的邏輯物件資源。簡化了應用程式的連線池改造。
-資源封裝。複雜的資源管理被封裝在 Snap-ConnectionPool內部,不需要應用系統過多的干涉。管理操作的可靠性、安全性由連線池保證。應用的干涉(如:主動關閉資源),只起到優化系統效能的作用,遺漏操作不會帶來負面影響。
-資源合理應用。按照JDBC中資源的從屬關係,Snap-ConnectionPool不僅對Connection進行緩衝處理,對Statement也有相應的機制處理。在2.3已描述,合理運用Connection和Statement之間的關係,可以更大限度地使用資源。所以,Snap-ConnectionPool封裝了Connection資源,通過內部管理PooledConnection,為應用系統提供更多的Statement資源。
-資源連鎖管理。Snap-ConnectionPool包含的三種邏輯物件,繼承了JDBC中相應物件之間的從屬關係。在內部管理中,也依照從屬關係進行連鎖管理。例如:判斷一個Connection是否超時,需要根據所包含的Statement是否活躍;判斷Statement也要根據ResultSet的活躍程度。
3.2連線池集中管理ConnectionManager
ConnectionPool是Snap-ConnectionPool的連線池物件。在Snap-ConnectionPool內部,可以指定多個不同的連線池(ConnectionPool)為應用服務。ConnectionManager管理所有的連線池,每個連線池以不同的名稱區別。通過配置檔案適應不同的資料庫種類。如下圖所示:
通過ConnectionManager,可以同時管理多個不同的連線池,提供通一的管理介面。在應用系統中通過ConnectionManager和相關的配置檔案,可以將凌亂散落在各自應用程式中的資料庫配置資訊(包括:資料庫名、使用者、密碼等資訊),集中在一個檔案中。便於系統的維護工作。
3.3連線池使用範例
對2.1的標準JDBC的使用範例,改為使用連線池,結果如下:
import java.sql.*;
import net.snapbug.util.dbtool.*;
…
..ConnectionPool dbConn = ConnectionManager
.getConnectionPool("testOracle" );
Statement st = dbConn.createStatement();
ResultSet rs = st.executeQuery(
“select * from demo_table” );
…
some data source operation
in herers.close();st.close();
在例子中,Snap-ConnectionPool封裝了應用對Connection的管理。只要改變JDBC獲取Connection的方法,為獲取連線池(ConnectionPool)(粗體部分),其他的資料操作都可以不做修改。按照這樣的方式,Snap-ConnectionPool可幫助應用有效地管理資料庫資源。如果應用忽視了最後資源的釋放: rs.close() 和 st.close(),連線池會通過超時(time-out)機制,自動回收。
4.小結
無論是Snap-ConnectionPool還是其他的資料庫連線池,都應當具備一下基本功能:
-對源資料庫資源的保護
-充分利用發揮資料庫的有效資源
-簡化應用的資料庫介面,封閉資源管理。
-對應用遺留資源的自動回收和整理,提高資源的再次利用率。
在這個前提下,應用程式才能投入更多的精力於各自的業務邏輯中。資料庫資源也不再成為系統的瓶頸。
注: 在網站 www.snapbug.net可免費下載Snap-ConnectionPool及更詳細的文件。
相關文章
- spring 簡單的使用 Hikari連線池 和 jdbc連線mysql 的一個簡單例子SpringJDBCMySql單例
- 連線zk 報錯連線不上hbase jdbcJDBC
- [尋]連線池例子
- Tomcat 的 JDBC 連線池TomcatJDBC
- 執行例子出錯,我的hibernate找不到JDBC連線?JDBC
- tomcat 配置JDBC連線池TomcatJDBC
- Angular Reactive Form 的一個具體使用例子AngularReactORM
- 使用 Angular Transfer State 的一個具體例子Angular
- JDBC連線三種資料庫例子JDBC資料庫
- 【JDBC】java連線池模擬測試 連線oracleJDBCJavaOracle
- 【JDBC】使用OracleDataSource建立連線池用於連線OracleJDBCOracle
- Remoting的事件機制(帶具體例子)REM事件
- 透過一個具體的例子理解 npm 的 peerDependencyNPM
- Jdbc 封裝, 利用反射, 加入連線池JDBC封裝反射
- JDBC資料庫連線池實現JDBC資料庫
- 一個不錯的Fortran教程
- 設計一個可靠的連線池
- SAP Spartacus SplitViewComponent Migration 的一個具體例子View
- Media Query 在 CSS 中使用的一個具體例子CSS
- Memcached 具體連線的哪個伺服器?伺服器
- 實現一個redis連線池Redis
- 淺談JDBC和資料庫連線池JDBC資料庫
- RxJS CombineLatest operator 的一個具體使用例子JS
- Java 的JDBC 資料庫連線池實現方法JavaJDBC資料庫
- JDBC、JDBC框架、資料庫事務、資料庫連線池JDBC框架資料庫
- 利用Oracle自帶的連線池類的一例 (轉)Oracle
- JDBC【資料庫連線池、DbUtils框架、分頁】JDBC資料庫框架
- 一個具體的例子學習Java volatile關鍵字Java
- 一個資料庫連線池的問題資料庫
- SAP CRM WebClient UI cross component跳轉的一個具體例子WebclientUIROS
- SAP UI5 使用 Smart Control 的一個具體例子UI
- SAP ABAP 寫時拷貝(Copy on Write)策略的一個具體例子
- Unity如何連線伺服器: 一個簡單的例子Unity伺服器
- Jdbc引入連線池,JdbcTemplate處理結果集的優化JDBC優化
- 這個 Redis 連線池的新監控方式針不戳~我再加一點佐料Redis
- Jdbc連線Oracle常見錯誤彙總JDBCOracle
- 使用 ViroReact 開發增強實現應用的一個具體例子React
- 帶你進入資料庫連線池資料庫