1.背景
數據庫連接的設計上有三種思路,第一是對於每一個用戶都創建一個連接,等到該用戶訪問完就將數據庫連接釋放。第二種是設置一個靜態連接變量,所有用戶都使用該連接。第三種就是使用數據庫連接池。
2.原理
在系統初始化的時候,將數據庫連接作爲對象存儲在內存中,當用戶需要訪問數據庫時,並非建立一個新的連接,而是從連接池中取出一個已建立的空閒連接對象。使用完畢後,用戶也並非將連接關閉,而是將連接放回連接池中,以供下一個請求訪問使用。而連接的建立、斷開都由連接池自身來管理。同時,還可以通過設置連接池的參數來控制連接池中的初始連接數、連接的上下限數以及每個連接的最大使用次數、最大空閒時間等等。也可以通過其自身的管理機制來監視數據庫連接的數量、使用情況等。
3.工具選擇
JDBC數據庫連接池的實現必須實現javax.sql.DataSource接口,其中DataSource稱爲數據源,該數據源的實現有以下三種:
C3p0:C3P0是一個開源的JDBC連接池,它實現了數據源和JNDI綁定,支持JDBC3規範和JDBC2的標準擴展。c3p0是異步操作的,緩慢的JDBC操作通過幫助進程完成。擴展這些操作可以有效的提升性能。目前使用它的開源項目有Hibernate,Spring等。c3p0有自動回收空閒連接功能。
DBCP:是Apache上的一個 java連接池項目,也是 tomcat使用的連接池組件。單獨使用dbcp需要3個包:common-dbcp.jar
,common-pool.jar
,common-collections.jar
由於建立數據庫連接是一個非常耗時耗資源的行爲,所以通過連接池預先同數據庫建立一些連接,放在內存中,應用程序需要建立數據庫連接時直接到連接池中申請一個就行,用完後再放回去。dbcp沒有自動的去回收空閒連接的功能。
Proxool:Proxool是一種Java數據庫連接池技術,是sourceforge下的一個開源項目,這個項目提供一個健壯、易用的連接池,最爲關鍵的是這個連接池提供監控的功能,方便易用,便於發現連接泄漏的情況。
對比結果:
性能dbcp<=c3p0<proxool
穩定性dbcp>=c3p0>proxool
4.c3p0代碼實現
準備
a)下載jar包,總共需要兩個包,c3p0-0.9.1.2.jar和mysql-connector-java-5.0.4-bin.jar
b)創建工程將兩個jar包導入,然後創建屬性文件c3p0.properties(只能是這樣的名字)
c)配置好c3p0.properties,其內容如下:
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://10.1.40.61:3306/test_bid_system?useUnicode=true&characterEncoding=utf8
c3p0.user=root
c3p0.password=root
c3p0.initialPoolSize=3
c3p0.minPoolSize=3
c3p0.maxPoolSize=15
c3p0.acquireIncrement=3
c3p0.maxIdleTime=1000
c3p0.acquireRetryAttempts=30
c3p0.acquireRetryDelay=1000
編碼
a)創建連接池類ConnectionPool.java
public class ConnectionPool {
private static ComboPooledDataSource ds;
private static ConnectionPool pool;
//私有的構造函數
private ConnectionPool(){
ds = new ComboPooledDataSource();
}
public static final ConnectionPool getInstance(){
if(pool == null){
pool = new ConnectionPool();
}
return pool;
}
//獲取連接池中的連接
public synchronized final Connection getConnection(){
try {
Connection conn = ds.getConnection();
return conn;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
b)創建測試類Test.java
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ConnectionPool pool = ConnectionPool.getInstance();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = pool.getConnection();
ps = conn.prepareStatement("select * from bms_weekreport");
rs = ps.executeQuery();
rs.next();
System.out.println("userId:"+rs.getString("userId"));
System.out.println("使用線程池連接數據庫!");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
rs.close();
ps.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}