1、什么時(shí)候使用?
連接池是用來建立一些和db的連接,使用戶訪問db時(shí)可以直接使用
這些現(xiàn)成的連接。
? 如果不建立連接池,每個(gè)用戶每一次訪問db時(shí)都要和db建立一次連接,
這樣db server 容易產(chǎn)生連接過多的錯(cuò)誤,用戶也會(huì)覺得速度很慢。
?? web編程,如果使用的是:客戶端---web server---db server.
這種架構(gòu)的,建議使用連接池的方法處理web server與db server間的
通訊。
2、如何檢測(cè)連接池,讓連接池配置更合理?
apache連接池使用
commons DBCP 配置參數(shù)簡(jiǎn)要說明 在配置時(shí),主要難以理解的主要有:removeAbandoned 、logAbandoned、removeAbandonedTimeout、maxWait這四個(gè)參數(shù),設(shè)置了rmoveAbandoned=true那么在getNumActive()快要到getMaxActive()的時(shí)候,系統(tǒng)會(huì)進(jìn)行無效的Connection的回收,回收的Connection為removeAbandonedTimeout(默認(rèn)300秒)中設(shè)置的秒數(shù)后沒有使用的Connection,激活回收機(jī)制好像是getNumActive()=getMaxActive()-2。? 有點(diǎn)忘了。 logAbandoned=true的話,將會(huì)在回收事件后,在log中打印出回收Connection的錯(cuò)誤信息,包括在哪個(gè)地方用了Connection卻忘記關(guān)閉了,在調(diào)試的時(shí)候很有用。 在這里私人建議maxWait的時(shí)間不要設(shè)得太長(zhǎng),maxWait如果設(shè)置太長(zhǎng)那么客戶端會(huì)等待很久才激發(fā)回收事件。 以下是我的配置的properties文件: #連接設(shè)置 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 #最大連接數(shù)量 dataSource.maxActive=50 #是否在自動(dòng)回收超時(shí)連接的時(shí)候打印連接的超時(shí)錯(cuò)誤 dataSource.logAbandoned=true #是否自動(dòng)回收超時(shí)連接 dataSource.removeAbandoned=true #超時(shí)時(shí)間(以秒數(shù)為單位) dataSource.removeAbandonedTimeout=180 #<!-- 超時(shí)等待時(shí)間以毫秒為單位 6000毫秒/1000等于60秒 --> dataSource.maxWait=1000 以下是我在連接控制中調(diào)用的方法:
- Properties??dbProps= null ; ??
- 取配置文件可以根據(jù)實(shí)際的不同修改 ??
- 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" ); ??
- ??? //是否在自動(dòng)回收超時(shí)連接的時(shí)候打印連接的超時(shí)錯(cuò)誤 ??
- ?? boolean ?logAbandoned?=?(Boolean.valueOf(dbProps.getProperty( "dataSource.logAbandoned" , "false" ))).booleanValue(); ??
- ??
- ?? //是否自動(dòng)回收超時(shí)連接 ??
- ?? boolean ?removeAbandoned?=?(Boolean.valueOf(dbProps.getProperty( "dataSource.removeAbandoned" , "false" ))).booleanValue(); ??
- ??
- ?? //超時(shí)時(shí)間(以秒數(shù)為單位) ??
- ?? int ?removeAbandonedTimeout?=?Integer.parseInt(dbProps.getProperty( "dataSource.removeAbandonedTimeout" , "300" )); ??
- ??
- ?dataSource?=? new ?BasicDataSource(); ??
- ?dataSource.setDriverClassName(driveClassName); ??
- ?dataSource.setUrl(url); ??
- ?dataSource.setUsername(username); ??
- ?dataSource.setPassword(password); ??
- ??
- ? //初始化連接數(shù) ??
- ? if (initialSize!= null ) ??
- ??dataSource.setInitialSize(Integer.parseInt(initialSize)); ??
- ? ??
- ? //最小空閑連接 ??
- ? if (minIdle!= null ) ??
- ??dataSource.setMinIdle(Integer.parseInt(minIdle)); ??
- ??
- ? //最大空閑連接 ??
- ? if (maxIdle!= null ) ??
- ??dataSource.setMaxIdle(Integer.parseInt(maxIdle)); ??
- ? ??
- ? //超時(shí)回收時(shí)間(以毫秒為單位) ??
- ? if (maxWait!= null ) ??
- ??dataSource.setMaxWait(Long.parseLong(maxWait)); ??
- ? ??
- ? //最大連接數(shù) ??
- ? 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( "創(chuàng)建連接池時(shí),無法取得連接!檢查設(shè)置!!!" ); ??
- ?} else { ??
- ??conn.close(); ??
- ?} ??
- ?System.out.println( "連接池創(chuàng)建成功!!!" ); ??
- } ??
- catch ?(Exception?e)?{ ??
- ?e.printStackTrace(); ??
- ????System.out.println( "創(chuàng)建連接池失敗!請(qǐng)檢查設(shè)置!!!" ); ??
- }??
Properties dbProps=null; //下面的讀取配置文件可以根據(jù)實(shí)際的不同修改 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"); //是否在自動(dòng)回收超時(shí)連接的時(shí)候打印連接的超時(shí)錯(cuò)誤 boolean logAbandoned = (Boolean.valueOf(dbProps.getProperty("dataSource.logAbandoned","false"))).booleanValue(); //是否自動(dòng)回收超時(shí)連接 boolean removeAbandoned = (Boolean.valueOf(dbProps.getProperty("dataSource.removeAbandoned","false"))).booleanValue(); //超時(shí)時(shí)間(以秒數(shù)為單位) int removeAbandonedTimeout = Integer.parseInt(dbProps.getProperty("dataSource.removeAbandonedTimeout","300")); dataSource = new BasicDataSource(); dataSource.setDriverClassName(driveClassName); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); //初始化連接數(shù) if(initialSize!=null) dataSource.setInitialSize(Integer.parseInt(initialSize)); //最小空閑連接 if(minIdle!=null) dataSource.setMinIdle(Integer.parseInt(minIdle)); //最大空閑連接 if(maxIdle!=null) dataSource.setMaxIdle(Integer.parseInt(maxIdle)); //超時(shí)回收時(shí)間(以毫秒為單位) if(maxWait!=null) dataSource.setMaxWait(Long.parseLong(maxWait)); //最大連接數(shù) 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("創(chuàng)建連接池時(shí),無法取得連接!檢查設(shè)置!!!"); }else{ conn.close(); } System.out.println("連接池創(chuàng)建成功!!!"); } catch (Exception e) { e.printStackTrace(); System.out.println("創(chuàng)建連接池失敗!請(qǐng)檢查設(shè)置!!!"); }
用apache的dbcp來建立獨(dú)立的數(shù)據(jù)庫(kù)連接池(db connection pool)
數(shù)據(jù)庫(kù)連接池的好處是不言而喻的,現(xiàn)在大部分的application server都提供自己的數(shù)據(jù)庫(kù)連接池方案,此時(shí),只要按照application server的文檔說明,正確配置,即可在應(yīng)用中享受到數(shù)據(jù)庫(kù)連接池的好處。
但是,有些時(shí)候,我們的應(yīng)用是個(gè)獨(dú)立的java application,并不是普通的WEB/J2EE應(yīng)用,而且是單獨(dú)運(yùn)行的,不要什么application server的配合,這種情況下,我們就需要建立自己的數(shù)據(jù)庫(kù)連接池方案了。這里,介紹如何利用apache的dbcp來建立為民自己的數(shù)據(jù)庫(kù)連接池。
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/
在建立我們自己的數(shù)據(jù)庫(kù)連接池時(shí),可以使用xml文件來傳入需要的參數(shù),這里只使用hard code的方式來簡(jiǎn)單介紹,所有需要我們自己寫的代碼很少,只要建立一個(gè)文件如下:
- 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; } }
接下來,在我們的應(yīng)用中,只要簡(jiǎn)單地使用ConnectionSource.getConnection()就可以取得連接池中的數(shù)據(jù)庫(kù)連接,享受數(shù)據(jù)庫(kù)連接帶給我們的好處了。當(dāng)我們使用完取得的數(shù)據(jù)庫(kù)連接后,只要簡(jiǎn)單地使用connection.close()就可把此連接返回到連接池中,至于為什么不是直接關(guān)閉此連接,而是返回給連接池,這是因?yàn)閐bcp使用委派模型來實(shí)現(xiàn)Connection接口了。
在使用Properties來創(chuàng)建BasicDataSource時(shí),有很多參數(shù)可以設(shè)置,比較重要的還有:
testOnBorrow、testOnReturn、testWhileIdle,他們的意思是當(dāng)是取得連接、返回連接或連接空閑時(shí)是否進(jìn)行有效性驗(yàn)證(即是否還和數(shù)據(jù)庫(kù)連通的),默認(rèn)都為false。所以當(dāng)數(shù)據(jù)庫(kù)連接因?yàn)槟撤N原因斷掉后,再?gòu)倪B接池中取得的連接,實(shí)際上可能是無效的連接了,所以,為了確保取得的連接是有效的, 可以把把這些屬性設(shè)為true。當(dāng)進(jìn)行校驗(yàn)時(shí),需要另一個(gè)參數(shù):validationQuery,對(duì)oracle來說,可以是:SELECT COUNT(*) FROM DUAL,實(shí)際上就是個(gè)簡(jiǎn)單的SQL語(yǔ)句,驗(yàn)證時(shí),就是把這個(gè)SQL語(yǔ)句在數(shù)據(jù)庫(kù)上跑一下而已,如果連接正常的,當(dāng)然就有結(jié)果返回了。
還有2個(gè)參數(shù):timeBetweenEvictionRunsMillis 和 minEvictableIdleTimeMillis, 他們兩個(gè)配合,可以持續(xù)更新連接池中的連接對(duì)象,當(dāng)timeBetweenEvictionRunsMillis 大于0時(shí),每過timeBetweenEvictionRunsMillis 時(shí)間,就會(huì)啟動(dòng)一個(gè)線程,校驗(yàn)連接池中閑置時(shí)間超過minEvictableIdleTimeMillis的連接對(duì)象。
原文參考
http://blog.csdn.net/zllsdn/archive/2006/11/20/1398577.aspx
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

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