連接池
1)傳統方式找DriverManager要連接,數目是有限的。
2)傳統方式的close(),並沒有將Connection重用,只是切斷應用程序和數據庫的橋樑,即無發送到SQL命令到數據庫端執行
3)項目中,對於Connection不說,不會直接使用DriverManager取得,而使用連接池方式。
4)DBCP和C3P0,都是Java開源的,都必須直接或間接實現javax.sql.DataSource接口
5)DBCP連接池需要dbcp.properties文件,同時需加入3個對應的jar包
*6)C3P0連接池需要在/WEB-INF/classes/目錄下存放c3p0-config.xml文件,該類ComboPooledDataSource在創建時
會自動在指定的目錄下找xml文件,並加載默認設置
7)重構JdbcUtil類
DBCP連接池
l DBCP 是 Apache 軟件基金組織下的開源連接池實現,使用DBCP數據源,應用程序應在系統中增加如下兩個 jar 文件:
• commons-dbcp.jar:連接池的實現
• commons-pool.jar: 連接池實現的依賴類
• commons-collections.jar :連接池實現的集合類
l Tomcat 的連接池正是採用該連接池來實現的。
#dbcp.properties 配置文件
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mydb2
username=root
password=root
關鍵代碼
static{
InputStreamin = JdbcUtil.class.getClassLoader().
getResourceAsStream("dbcp.properties");
Propertiesprop = new Properties();
prop.load(in);
BasicDataSourceFactoryfactory = new BasicDataSourceFactory();
dataSource = factory.createDataSource(prop);
}
實例代碼:
//測試連接池DBCP的用法
publicclass Demo2 {
publicstaticvoid main(String[] args) throws Exception {
long begin = System.currentTimeMillis();
//加載屬性文件
InputStream is = Demo2.class.getClassLoader().getResourceAsStream("dbcp.properties");
Properties props = new Properties();
props.load(is);
//創建DBCP連接池工廠
BasicDataSourceFactory factory = new BasicDataSourceFactory();
//創建數據源,即連接池
DataSource ds = factory.createDataSource(props);
for(int i=1;i<=50000;i++){
//從連接池中取得一個空閒的連接對象
Connection conn = ds.getConnection();
if(conn!=null){
System.out.println(i+":取得連接");
}
//將連接對象還回給連接池
conn.close();
}
long end = System.currentTimeMillis();
System.out.println("共用" + (end-begin)/1000+"秒");
}
}
c3p0:
配置文件:
<?xml version="1.0"encoding="UTF-8"?>
<!-- 文件名不能亂改,須用默認的c3o0-config.xml -->
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/mydb2</property>
</default-config>
</c3p0-config>
/推薦使用c3p0連接池
//測試連接池C3P0的用法
publicclass Demo3 {
publicstaticvoid main(String[] args) throws Exception {
long begin = System.currentTimeMillis();
//創建C3P0連接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
for(int i=1;i<=100000;i++){
Connection conn = dataSource.getConnection();
if(conn!=null){
System.out.println(i+":取得連接");
conn.close();
}
}
long end = System.currentTimeMillis();
System.out.println("共用" + (end-begin)/1000+"秒");
}
}
JdbcUtil工具類,封裝從c3p0的連接池獲取連接:
//JDBC工具類:關閉流和取得連接
publicfinalclass JdbcUtil3 {
//數據源
privatestatic ComboPooledDataSource dataSource;
static{//靜態塊,讀取c3p0默認配置文件
dataSource = new ComboPooledDataSource();
}
//取得連接
publicstatic Connection getMySqlConnection() throws SQLException{
return dataSource.getConnection();
}
//關閉連接
publicstaticvoid close(Connection conn) throws SQLException{
if(conn!=null){
conn.close();
}
}
}
C3P0連接池具體參數說明如下:
c3p0-config>
<default-config>
<!--當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數。Default:3
-->
<propertyname="acquireIncrement">3</property>
<!--定義在從數據庫獲取新連接失敗後重復嘗試的次數。Default: 30 -->
<property name="acquireRetryAttempts">30</property>
<!--兩次連接中間隔時間,單位毫秒。Default:1000 -->
<property name="acquireRetryDelay">1000</property>
<!--連接關閉時默認將所有未提交的操作回滾。Default:false -->
<propertyname="autoCommitOnClose">false</property>
<!--c3p0將建一張名爲Test的空表,並使用其自帶的查詢語句進行測試。如果定義了這個參數那麼
屬性preferredTestQuery將被忽略。你不能在這張Test表上進行任何操作,它將只供c3p0測試
使用。Default:null-->
<propertyname="automaticTestTable">Test</property>
<!--獲取連接失敗將會引起所有等待連接池來獲取連接的線程拋出異常。但是數據源仍有效
保留,並在下次調用getConnection()的時候繼續嘗試獲取連接。如果設爲true,那麼在嘗試
獲取連接失敗後該數據源將申明已斷開並永久關閉。Default: false-->
<property name="breakAfterAcquireFailure">false</property>
<!--當連接池用完時客戶端調用getConnection()後等待獲取新連接的時間,超時後將拋出
SQLException,如設爲0則無限期等待。單位毫秒。Default: 0 -->
<property name="checkoutTimeout">100</property>
<!--通過實現ConnectionTester或QueryConnectionTester的類來測試連接。類名需制定全路徑。
Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester-->
<propertyname="connectionTesterClassName"></property>
<!--指定c3p0 libraries的路徑,如果(通常都是這樣)在本地即可獲得那麼無需設置,默認null即可
Default: null-->
<propertyname="factoryClassLocation">null</property>
<!--Stronglydisrecommended. Setting this to true may lead to subtle and bizarre bugs.
(文檔原文)作者強烈建議不使用的一個屬性-->
<propertyname="forceIgnoreUnresolvedTransactions">false</property>
<!--每60秒檢查所有連接池中的空閒連接。Default:
0 -->
<property name="idleConnectionTestPeriod">60</property>
<!--初始化時獲取三個連接,取值應在minPoolSize與maxPoolSize之間。Default:
3 -->
<property name="initialPoolSize">3</property>
<!--最大空閒時間,60秒內未使用則連接被丟棄。若爲0則永不丟棄。Default:
0 -->
<propertyname="maxIdleTime">60</property>
<!--連接池中保留的最大連接數。Default:15 -->
<property name="maxPoolSize">15</property>
<!--JDBC的標準參數,用以控制數據源內加載的PreparedStatements數量。但由於預緩存的statements
屬於單個connection而不是整個連接池。所以設置這個參數需要考慮到多方面的因素。
如果maxStatements與maxStatementsPerConnection均爲0,則緩存被關閉。Default:
0-->
<property name="maxStatements">100</property>
<!--maxStatementsPerConnection定義了連接池內單個連接所擁有的最大緩存statements數。Default:
0 -->
<propertyname="maxStatementsPerConnection"></property>
<!--c3p0是異步操作的,緩慢的JDBC操作通過幫助進程完成。擴展這些操作可以有效的提升性能
通過多線程實現多個操作同時被執行。Default:3-->
<property name="numHelperThreads">3</property>
<!--當用戶調用getConnection()時使root用戶成爲去獲取連接的用戶。主要用於連接池連接非c3p0
的數據源時。Default:null-->
<propertyname="overrideDefaultUser">root</property>
<!--與overrideDefaultUser參數對應使用的一個參數。Default:null-->
<property name="overrideDefaultPassword">password</property>
<!--密碼。Default: null-->
<property name="password"></property>
<!--定義所有連接測試都執行的測試語句。在使用連接測試的情況下這個一顯著提高測試速度。注意:
測試的表必須在初始數據源的時候就存在。Default:null-->
<propertyname="preferredTestQuery">select id from test whereid=1</property>
<!--用戶修改系統配置參數執行前最多等待300秒。Default:
300 -->
<property name="propertyCycle">300</property>
<!--因性能消耗大請只在需要的時候使用它。如果設爲true那麼在每個connection提交的
時候都將校驗其有效性。建議使用idleConnectionTestPeriod或automaticTestTable
等方法來提升連接測試的性能。Default:false -->
<propertyname="testConnectionOnCheckout">false</property>
<!--如果設爲true那麼在取得連接的同時將校驗連接的有效性。Default:false
-->
<propertyname="testConnectionOnCheckin">true</property>
<!--用戶名。Default: null-->
<propertyname="user">root</property>
<!--早期的c3p0版本對JDBC接口採用動態反射代理。在早期版本用途廣泛的情況下這個參數
允許用戶恢復到動態反射代理以解決不穩定的故障。最新的非反射代理更快並且已經開始
廣泛的被使用,所以這個參數未必有用。現在原先的動態反射與新的非反射代理同時受到
支持,但今後可能的版本可能不支持動態反射代理。Default: false-->
<propertyname="usesTraditionalReflectiveProxies">false</property>
<property name="automaticTestTable">con_test</property>
<propertyname="checkoutTimeout">30000</property>
<propertyname="idleConnectionTestPeriod">30</property>
<propertyname="initialPoolSize">10</property>
<propertyname="maxIdleTime">30</property>
<propertyname="maxPoolSize">25</property>
<propertyname="minPoolSize">10</property>
<propertyname="maxStatements">0</property>
<user-overrides user="swaldman">
</user-overrides>
</default-config>
<named-config name="dumbTestConfig">
<propertyname="maxStatements">200</property>
<user-overrides user="poop">
<propertyname="maxStatements">300</property>
</user-overrides>
</named-config>
</c3p0-config>