1、什么時候使用?
連接池是用來建立一些和db的連接,使用戶訪問db時可以直接使用
這些現成的連接。
? 如果不建立連接池,每個用戶每一次訪問db時都要和db建立一次連接,
這樣db server 容易產生連接過多的錯誤,用戶也會覺得速度很慢。
?? web編程,如果使用的是:客戶端---web server---db server.
這種架構的,建議使用連接池的方法處理web server與db server間的
通訊。
2、如何檢測連接池,讓連接池配置更合理?
apache連接池使用
commons DBCP 配置參數簡要說明 在配置時,主要難以理解的主要有:removeAbandoned 、logAbandoned、removeAbandonedTimeout、maxWait這四個參數,設置了rmoveAbandoned=true那么在getNumActive()快要到getMaxActive()的時候,系統會進行無效的Connection的回收,回收的Connection為removeAbandonedTimeout(默認300秒)中設置的秒數后沒有使用的Connection,激活回收機制好像是getNumActive()=getMaxActive()-2。? 有點忘了。 logAbandoned=true的話,將會在回收事件后,在log中打印出回收Connection的錯誤信息,包括在哪個地方用了Connection卻忘記關閉了,在調試的時候很有用。 在這里私人建議maxWait的時間不要設得太長,maxWait如果設置太長那么客戶端會等待很久才激發回收事件。 以下是我的配置的properties文件: #連接設置 jdbc.driverClassName=oracle.jdbc.driver.OracleDriver jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:DBSERVER jdbc.username=user jdbc.password=pass #<!-- 初始化連接 --> dataSource.initialSize=10 #<!-- 最大空閑連接 --> dataSource.maxIdle=20 #<!-- 最小空閑連接 --> dataSource.minIdle=5 #最大連接數量 dataSource.maxActive=50 #是否在自動回收超時連接的時候打印連接的超時錯誤 dataSource.logAbandoned=true #是否自動回收超時連接 dataSource.removeAbandoned=true #超時時間(以秒數為單位) dataSource.removeAbandonedTimeout=180 #<!-- 超時等待時間以毫秒為單位 6000毫秒/1000等于60秒 --> dataSource.maxWait=1000 以下是我在連接控制中調用的方法:
- Properties??dbProps= null ; ??
- 取配置文件可以根據實際的不同修改 ??
- dbProps?=?ConfigProperties.getInstance().getProperties( "jdbc.properties" ); ??
- try ?{ ??
- ?String?driveClassName?=?dbProps.getProperty( "jdbc.driverClassName" ); ??
- ?String?url?=?dbProps.getProperty( "jdbc.url" ); ??
- ?String?username?=?dbProps.getProperty( "jdbc.username" ); ??
- ?String?password?=?dbProps.getProperty( "jdbc.password" ); ??
- ? ??
- ?String?initialSize?=?dbProps.getProperty( "dataSource.initialSize" ); ??
- ?String?minIdle?=?dbProps.getProperty( "dataSource.minIdle" ); ??
- ?String?maxIdle?=?dbProps.getProperty( "dataSource.maxIdle" ); ??
- ?String?maxWait?=?dbProps.getProperty( "dataSource.maxWait" ); ??
- ?String?maxActive?=?dbProps.getProperty( "dataSource.maxActive" ); ??
- ??? //是否在自動回收超時連接的時候打印連接的超時錯誤 ??
- ?? boolean ?logAbandoned?=?(Boolean.valueOf(dbProps.getProperty( "dataSource.logAbandoned" , "false" ))).booleanValue(); ??
- ??
- ?? //是否自動回收超時連接 ??
- ?? boolean ?removeAbandoned?=?(Boolean.valueOf(dbProps.getProperty( "dataSource.removeAbandoned" , "false" ))).booleanValue(); ??
- ??
- ?? //超時時間(以秒數為單位) ??
- ?? int ?removeAbandonedTimeout?=?Integer.parseInt(dbProps.getProperty( "dataSource.removeAbandonedTimeout" , "300" )); ??
- ??
- ?dataSource?=? new ?BasicDataSource(); ??
- ?dataSource.setDriverClassName(driveClassName); ??
- ?dataSource.setUrl(url); ??
- ?dataSource.setUsername(username); ??
- ?dataSource.setPassword(password); ??
- ??
- ? //初始化連接數 ??
- ? if (initialSize!= null ) ??
- ??dataSource.setInitialSize(Integer.parseInt(initialSize)); ??
- ? ??
- ? //最小空閑連接 ??
- ? if (minIdle!= null ) ??
- ??dataSource.setMinIdle(Integer.parseInt(minIdle)); ??
- ??
- ? //最大空閑連接 ??
- ? if (maxIdle!= null ) ??
- ??dataSource.setMaxIdle(Integer.parseInt(maxIdle)); ??
- ? ??
- ? //超時回收時間(以毫秒為單位) ??
- ? if (maxWait!= null ) ??
- ??dataSource.setMaxWait(Long.parseLong(maxWait)); ??
- ? ??
- ? //最大連接數 ??
- ? if (maxActive!= null ){ ??
- ?? if (!maxActive.trim().equals( "0" )) ??
- ???dataSource.setMaxActive(Integer.parseInt(maxActive)); ??
- ?} ??
- ??
- ?System.out.println( "logAbandoned=" +logAbandoned); ??
- ????dataSource.setLogAbandoned(logAbandoned); ??
- ?dataSource.setRemoveAbandoned(removeAbandoned); ??
- ?dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout); ??
- ? ??
- ?Connection?conn?=?dataSource.getConnection(); ??
- ? if (conn== null ){ ??
- ??log( "創建連接池時,無法取得連接!檢查設置!!!" ); ??
- ?} else { ??
- ??conn.close(); ??
- ?} ??
- ?System.out.println( "連接池創建成功!!!" ); ??
- } ??
- catch ?(Exception?e)?{ ??
- ?e.printStackTrace(); ??
- ????System.out.println( "創建連接池失敗!請檢查設置!!!" ); ??
- }??
Properties dbProps=null; //下面的讀取配置文件可以根據實際的不同修改 dbProps = ConfigProperties.getInstance().getProperties("jdbc.properties"); try { String driveClassName = dbProps.getProperty("jdbc.driverClassName"); String url = dbProps.getProperty("jdbc.url"); String username = dbProps.getProperty("jdbc.username"); String password = dbProps.getProperty("jdbc.password"); String initialSize = dbProps.getProperty("dataSource.initialSize"); String minIdle = dbProps.getProperty("dataSource.minIdle"); String maxIdle = dbProps.getProperty("dataSource.maxIdle"); String maxWait = dbProps.getProperty("dataSource.maxWait"); String maxActive = dbProps.getProperty("dataSource.maxActive"); //是否在自動回收超時連接的時候打印連接的超時錯誤 boolean logAbandoned = (Boolean.valueOf(dbProps.getProperty("dataSource.logAbandoned","false"))).booleanValue(); //是否自動回收超時連接 boolean removeAbandoned = (Boolean.valueOf(dbProps.getProperty("dataSource.removeAbandoned","false"))).booleanValue(); //超時時間(以秒數為單位) int removeAbandonedTimeout = Integer.parseInt(dbProps.getProperty("dataSource.removeAbandonedTimeout","300")); dataSource = new BasicDataSource(); dataSource.setDriverClassName(driveClassName); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); //初始化連接數 if(initialSize!=null) dataSource.setInitialSize(Integer.parseInt(initialSize)); //最小空閑連接 if(minIdle!=null) dataSource.setMinIdle(Integer.parseInt(minIdle)); //最大空閑連接 if(maxIdle!=null) dataSource.setMaxIdle(Integer.parseInt(maxIdle)); //超時回收時間(以毫秒為單位) if(maxWait!=null) dataSource.setMaxWait(Long.parseLong(maxWait)); //最大連接數 if(maxActive!=null){ if(!maxActive.trim().equals("0")) dataSource.setMaxActive(Integer.parseInt(maxActive)); } System.out.println("logAbandoned="+logAbandoned); dataSource.setLogAbandoned(logAbandoned); dataSource.setRemoveAbandoned(removeAbandoned); dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout); Connection conn = dataSource.getConnection(); if(conn==null){ log("創建連接池時,無法取得連接!檢查設置!!!"); }else{ conn.close(); } System.out.println("連接池創建成功!!!"); } catch (Exception e) { e.printStackTrace(); System.out.println("創建連接池失敗!請檢查設置!!!"); }
用apache的dbcp來建立獨立的數據庫連接池(db connection pool)
數據庫連接池的好處是不言而喻的,現在大部分的application server都提供自己的數據庫連接池方案,此時,只要按照application server的文檔說明,正確配置,即可在應用中享受到數據庫連接池的好處。
但是,有些時候,我們的應用是個獨立的java application,并不是普通的WEB/J2EE應用,而且是單獨運行的,不要什么application server的配合,這種情況下,我們就需要建立自己的數據庫連接池方案了。這里,介紹如何利用apache的dbcp來建立為民自己的數據庫連接池。
1。首先,下載必須的jar包
dbcp包,目前版本是1.2.1:http://jakarta.apache.org/commons/dbcp/
pool包,目前版本是1.3:http://jakarta.apache.org/commons/pool/,
如果下載的pool包是1.2的版本,還要下載common-collections包:http://jakarta.apache.org/commons/collections/
在建立我們自己的數據庫連接池時,可以使用xml文件來傳入需要的參數,這里只使用hard code的方式來簡單介紹,所有需要我們自己寫的代碼很少,只要建立一個文件如下:
- import ?org.apache.commons.dbcp.BasicDataSource; ??
- import ?org.apache.commons.dbcp.BasicDataSourceFactory; ??
- ??
- import ?java.sql.SQLException; ??
- import ?java.sql.Connection; ??
- import ?java.util.Properties; ??
- ??
- public ? class ?ConnectionSource?{ ??
- ???? private ? static ?BasicDataSource?dataSource?=? null ; ??
- ??
- ???? public ?ConnectionSource()?{ ??
- ????} ??
- ??
- ???? public ? static ? void ?init()?{ ??
- ??
- ???????? if ?(dataSource?!=? null )?{ ??
- ???????????? try ?{ ??
- ????????????????dataSource.close(); ??
- ????????????}? catch ?(Exception?e)?{ ??
- ???????????????? // ??
- ????????????} ??
- ????????????dataSource?=? null ; ??
- ????????} ??
- ??
- ???????? try ?{ ??
- ????????????Properties?p?=? new ?Properties(); ??
- ????????????p.setProperty( "driverClassName" ,? "oracle.jdbc.driver.OracleDriver" ); ??
- ????????????p.setProperty( "url" ,? "jdbc:oracle:thin:@192.168.0.1:1521:testDB" ); ??
- ????????????p.setProperty( "password" ,? "scott" ); ??
- ????????????p.setProperty( "username" ,? "tiger" ); ??
- ????????????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)?{ ??
- ???????????? // ??
- ????????} ??
- ????} ??
- ??
- ??
- ???? public ? static ? synchronized ?Connection?getConnection()? throws ??SQLException?{ ??
- ???????? if ?(dataSource?==? null )?{ ??
- ????????????init(); ??
- ????????} ??
- ????????Connection?conn?=? null ; ??
- ???????? if ?(dataSource?!=? null )?{ ??
- ????????????conn?=?dataSource.getConnection(); ??
- ????????} ??
- ???????? return ?conn; ??
- ????} ??
- }??
import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; import java.sql.SQLException; import java.sql.Connection; import java.util.Properties; public class ConnectionSource { private static BasicDataSource dataSource = null; public ConnectionSource() { } public static void init() { if (dataSource != null) { try { dataSource.close(); } catch (Exception e) { // } dataSource = null; } try { Properties p = new Properties(); p.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver"); p.setProperty("url", "jdbc:oracle:thin:@192.168.0.1:1521:testDB"); p.setProperty("password", "scott"); p.setProperty("username", "tiger"); 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) { // } } public static synchronized Connection getConnection() throws SQLException { if (dataSource == null) { init(); } Connection conn = null; if (dataSource != null) { conn = dataSource.getConnection(); } return conn; } }
接下來,在我們的應用中,只要簡單地使用ConnectionSource.getConnection()就可以取得連接池中的數據庫連接,享受數據庫連接帶給我們的好處了。當我們使用完取得的數據庫連接后,只要簡單地使用connection.close()就可把此連接返回到連接池中,至于為什么不是直接關閉此連接,而是返回給連接池,這是因為dbcp使用委派模型來實現Connection接口了。
在使用Properties來創建BasicDataSource時,有很多參數可以設置,比較重要的還有:
testOnBorrow、testOnReturn、testWhileIdle,他們的意思是當是取得連接、返回連接或連接空閑時是否進行有效性驗證(即是否還和數據庫連通的),默認都為false。所以當數據庫連接因為某種原因斷掉后,再從連接池中取得的連接,實際上可能是無效的連接了,所以,為了確保取得的連接是有效的, 可以把把這些屬性設為true。當進行校驗時,需要另一個參數:validationQuery,對oracle來說,可以是:SELECT COUNT(*) FROM DUAL,實際上就是個簡單的SQL語句,驗證時,就是把這個SQL語句在數據庫上跑一下而已,如果連接正常的,當然就有結果返回了。
還有2個參數:timeBetweenEvictionRunsMillis 和 minEvictableIdleTimeMillis, 他們兩個配合,可以持續更新連接池中的連接對象,當timeBetweenEvictionRunsMillis 大于0時,每過timeBetweenEvictionRunsMillis 時間,就會啟動一個線程,校驗連接池中閑置時間超過minEvictableIdleTimeMillis的連接對象。
原文參考
http://blog.csdn.net/zllsdn/archive/2006/11/20/1398577.aspx
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
