記性不如爛筆頭21-JAVA資料庫連接池 DBCP,21-javadbcp
使用者每次請求都需要向資料庫獲得連結,而資料庫建立串連通常需要消耗相對較大的資源,建立時間也較長。假設網站一天100萬訪問量,資料庫伺服器就需要建立100萬次串連,極大的浪費資料庫的資源,並且極易造成資料庫伺服器串連數溢出,並且使用者的使用也會很慢,影響使用者體驗;
對資料庫連接的管理能顯著影響到整個應用程式的伸縮性和健壯性,影響到程式的效能指標。
資料庫連接池針對這些問題建立出來。資料庫連接池負責分配,管理和釋放資料庫資源,它允許應用程式重複使用一個現有的資料庫連接,而不是重建立立一個。
資料庫連接池在初始化時將建立一定數量的資料庫連接放到串連池中,這些資料庫連接的數量是由最小資料庫連接數來設定的.無論這些資料庫連接是否被使用,串連池都將一直保證至少擁有這麼多的串連數量.串連池的最大資料庫連接數量限定了這個串連池能佔有的最大串連數,當應用程式向串連池請求的串連數超過最大串連數量時,這些請求將被加入到等待隊列中.
資料庫連接池的最小串連數和最大串連數的是最重要的兩個參數指標。
最小串連數:是串連池一直保持的資料庫連接,所以如果應用程式對資料庫連接的使用量不大,將會有大量的資料庫連接資源被浪費.
最大串連數:是串連池能申請的最大串連數,如果資料庫連接請求超過次數,後面的資料庫連接請求將被加入到等待隊列中,這會影響以後的資料庫操作
1、原始碼資料來源(DataSource)
DataSource的實現,按其英文含義稱之為資料來源,資料來源中都包含了資料庫連接池的實現。現在很多WEB伺服器(Weblogic, WebSphere, Tomcat)都提供了內建的DataSoruce的管理。
也有一些開源組織提供了資料來源的其他實現,比如著名的有DBCP 資料庫連接池、C3P0 資料庫連接池等。
DBCP 是 Apache軟體基金組織下的開源串連池實現,要使用DBCP資料來源,需要應用程式應在系統中增加如下兩個 jar 檔案:
Commons-dbcp.jar:串連池的實現
Commons-pool.jar:串連池實現的依賴庫
Tomcat6.0已經以前版本的串連池正是採用該串連池來實現的。該資料庫連接池既可以與應用伺服器整合使用,也可由應用程式獨立使用。(tomcat7.0版本使用了內建的串連池)
2、DBCP必須配置的參數
Username 建立資料庫連接的使用者名稱;
Password 建立資料庫連接的密碼;
URL 傳遞給JDBC驅動的用於建立串連的URL
DriverClassName 使用的JDBC驅動的完整有效java 類名
connectionProperties 當建立新串連時被發送給JDBC驅動的串連參數,格式必須是key=value格式
3、DBCP其他參數詳解
initialSize 初始化串連:串連池啟動時建立的初始化串連數量
maxActive 最大活動串連:串連池在同一時間能夠分配的最大活動串連的數量,類似於並發量,設為0表示無限制 ,2.0版本中,已經去掉該方法,對應替代的方法為:setMaxTotal();
maxIdle 最大空閑串連:串連池中容許保持空閑狀態的最大串連數量,超過的空閑串連將被釋放,如果設定為負數表示不限制。
minIdle 最小空閑串連:串連池中容許保持空閑狀態的最小串連數量,低於這個數量將建立新的串連,如果設定為0則不建立
maxWait 最大建立串連等待時間:當沒有可用串連時,串連池等待串連被歸還的最大時間(以毫秒計數),超過時間則拋出異常,如果設定為-1表示無限等,2.0中已經去掉該方法,替代方法為:setMaxWaitMillis();
removeAbandoned 是否自動回收逾時串連
removeAbandonedTimeout 設定逾時時間有一個要注意的地方,逾時時間=現在的時間-程式中建立Connection的時間,如果 maxActive比較大,比如超過100,那麼removeAbandonedTimeout可以設定長一點比如180,也就是三分鐘無響應的串連進行回收,當然應用的不同設定長度也不同。
timeBetweenEvictionRunsMillis, minEvictableIdleTimeMillis一起使用,每timeBetweenEvictionRunsMillis毫秒秒檢查一次串連池中閒置串連,把空閑時間超過minEvictableIdleTimeMillis毫秒的串連斷開,直到串連池中的串連數到minIdle為止
testOnBorrow、testOnReturn、testWhileIdle,這些屬性的意義是取得、返回對象和空閑時是否進行驗證,檢查對象是否有效,預設都為false即不驗證。所以當使用DBCP時,資料庫連接因為某種原因斷掉後,再從串連池中取得串連又不進行驗證,這時取得的串連實際已經時無效的資料庫連接了。網上很多說DBCP的bug應該都是如此吧,只有把這些屬性設為true,再提供_validationQuery語句就可以保證資料庫連接始終有效了。
4、利用DBCP實現資料庫連接池的原始碼
package test.ffm83.commons.dbcp;
importorg.apache.commons.dbcp.BasicDataSource;
importorg.apache.commons.dbcp.BasicDataSourceFactory;
import org.apache.commons.lang.StringUtils;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Connection;
import java.util.Properties;
/* 通過dbcp串連oracle資料庫
*使用1.4版本實現
*@author 範芳銘
**/
public classDbcpUsage {
private static BasicDataSource dataSource = null;
public DbcpUsage() {
}
public static void init() {
if (dataSource != null) {
try {
dataSource.close();
}catch(Exception e) {
e.printStackTrace();
}
dataSource = null;
}
try {
Propertiesp = newProperties();
p.setProperty("driverClassName","oracle.jdbc.driver.OracleDriver");
p.setProperty("url","jdbc:oracle:thin:@192.168.19.1:1521:fanfangming");
p.setProperty("password","ffm");
p.setProperty("username","ffm");
p.setProperty("maxActive","30");
p.setProperty("maxIdle","10");
p.setProperty("maxWait","1000");
p.setProperty("removeAbandoned","false");
p.setProperty("removeAbandonedTimeout", "120");
p.setProperty("testOnBorrow","true");
p.setProperty("logAbandoned","true");
dataSource =(BasicDataSource)BasicDataSourceFactory
.createDataSource(p);
}catch(Exception e) {
e.printStackTrace();
}
}
public static synchronized ConnectiongetConnection() throwsSQLException{
if (dataSource == null) {
init();
}
Connectionconn = null;
if (dataSource != null) {
conn= dataSource.getConnection();
}
return conn;
}
public static void main(String[] args) throws Exception {
Connectioncon = null;
try {
con= DbcpUsage.getConnection();
Stringsql = " select sysdate from dual";
PreparedStatement ps =con.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
String value =rs.getString("sysdate");
System.out.println(StringUtils.center(value+",資料庫連接成功", 50, "-"));
}
}catch(Exception e) {
e.printStackTrace();
}finally{
if (con != null) {
con.close();
}
}
}
}
運行如下:
----------2014-12-1612:38:32.0,資料庫連接成功-----------
5、運行結果
運行如下:
----------2014-12-1612:38:32.0,資料庫連接成功-----------