天天看點

資料庫連接配接池DataSource

什麼是資料庫連接配接池

資料庫連接配接是一種關鍵的有限的昂貴的資源,這一點在多使用者的網頁應用程式中展現得尤為突出。對資料庫連接配接的管理能顯著影響到整個應用程式的伸縮性和健壯性,影響到程式的性能名額。資料庫連接配接池正是針對這個問題提出來的。資料庫連接配接池負責配置設定、管理和釋放資料庫連接配接,它允許應用程式重複使用一個現有的資料庫連接配接,而不是再重建立立一個;釋放空閑時間超過最大空閑時間的資料庫連接配接來避免因為沒有釋放資料庫連接配接而引起的資料庫連接配接遺漏。這項技術能明顯提高對資料庫操作的性能。

以下是使用連接配接池與沒有使用連接配接池的一個比較圖例

資料庫連接配接池DataSource
資料庫連接配接池DataSource

連接配接池的優點

節省建立連接配接與釋放連接配接性能消耗

連接配接池中連接配接起到複用的作用,提供程式性能

其實使用連接配接池的時候,也是有點缺點的:

在程式最開始的時候必須加載連接配接池對象,是以肯定會消耗較多的資源,但是也比每次都建立連接配接消耗資源強。

連接配接池的原理

連接配接池基本的思想是在系統初始化的時候,将資料庫連接配接作為對象存儲在記憶體中,當使用者需要通路資料庫時,并非建立一個新的連接配接,而是從連接配接池中取出一個已建立的空閑連接配接對象。使用完畢後,使用者也并非将連接配接關閉,而是将連接配接放回連接配接池中,以供下一個請求通路使用。而連接配接的建立、斷開都由連接配接池自身來管理。同時,還可以通過設定連接配接池的參數來控制連接配接池中的初始連接配接數、連接配接的上下限數以及每個連接配接的最大使用次數、最大空閑時間等等。也可以通過其自身的管理機制來監視資料庫連接配接的數量、使用情況等。

用通俗的話來說就是:弄一個集合,扔幾個連接配接對象到集合(連接配接池)中,當使用者需要擷取連接配接時,從集合(連接配接池)中取出一個,使用完後再重新放回集合(連接配接池)中,以供下一次再使用,也就是連接配接池中的對象是可以重複使用的。

在了解了連接配接池實作的源碼後我試着模拟寫一個簡單版的連接配接池大概實作原理

public class MyDataSource {

	private LinkedList<Connection> ll;

	public MyDataSource() throws SQLException {
		ll = new LinkedList<Connection>();
		//當建立MyDataSource時就會向集合中添加10個Connection對象。
		for (int i = 0; i < 10; i++) {
//使用自己封裝的JdbcUtils工具類擷取一個連接配接對象
			ll.add(JdbcUtils.getConnection());
		}
	}

	// 擷取連接配接,将集合中的connection傳回一個
	public Connection getConnection() {
		return ll.removeLast();
	}
	// 關閉連接配接,将連接配接對象重新再放回集合中去
	public void closeConnection(Connection con) {
		ll.addFirst(con);
	}
}
           

下面是使用上面自己建立的資料庫連接配接池

public class DataSourceDemo1 {
 
public static void main(String[] args) throws SQLException {
String sql = "select * from account";
// 建立一個連接配接池
MyDataSource mds = new MyDataSource();
// 從連接配接池中擷取一個連接配接對象
Connection con = mds.getConnection();
 
ResultSet rs = con.prepareStatement(sql).executeQuery();
 
while (rs.next()) {
System.out.println(rs.getInt("id") + "  "
+ rs.getString("username") + "  " + rs.getString("money"));
}
 
rs.close();
//mds.closeConnection(con);//将連接配接對象重新放回到池中。
con.close();
}
}
           

連接配接池規定

javax.sql包下有一個 DataSource

所有的支援java的連接配接池都應該實作javax.sql.DataSource接口,在這個接口中提供了一個方法  getConnection()它就是擷取一個連接配接對象的。

如果連接配接對象Connection是通過連接配接池擷取的,當通過Connection對象調用close()方法時,不再是銷毀連接配接對象,而是将連接配接對象放回到連接配接池。是以Connection對象調用close()方法時,具體做什麼操作需要看這個Connection對象是怎麼來的。

1,如果就是普通擷取(驅動管理器DriverManager),那麼close()就是關閉連接配接。

2,如果是通過連接配接池(DataSource)擷取,那麼close()就是将連接配接對象重新放回連接配接池中。

具體實作方式是使用了動态代理在實作了DataSource接口後對父類Connection的方法進行了重寫。

畢竟在開發中,資料庫連接配接池不會讓我們去實作,了解了資料庫連接配接池的大概原理後,讓我們來看看常用的資料庫連接配接池有哪些以及在開發如何使用。

連接配接池的使用在項目中一般可以分為兩種,一種是直接在java代碼中以編碼的方式實作,另一種則是通過加載配置檔案的方式。

Dbcp連接配接池(了解)

DBCP 是 Apache 軟體基金組織下的開源連接配接池實作,使用DBCP資料源,應用程式應在系統中增加如下兩個 jar 檔案:

Commons-dbcp.jar:連接配接池的實作

Commons-pool.jar:連接配接池實作的依賴庫

Tomcat 的連接配接池正是采用該連接配接池來實作的。該資料庫連接配接池既可以與應用伺服器整合使用,也可由應用程式獨立使用。DBCP 是 Apache 軟體基金組織下的開源連接配接池實作,使用DBCP資料源,應用程式應在系統中增加如下兩個 jar 檔案:

Commons-dbcp.jar:連接配接池的實作

Commons-pool.jar:連接配接池實作的依賴庫

Tomcat 的連接配接池正是采用該連接配接池來實作的。該資料庫連接配接池既可以與應用伺服器整合使用,也可由應用程式獨立使用。

dbcp連接配接池編碼實作

// 1.建立連接配接池對象
BasicDataSource ds = new BasicDataSource();
// 2.設定相關屬性
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql:///day13");
ds.setUsername("root");
ds.setPassword("abc");
           

dbcp連接配接池配置檔案實作

//1.加載配置資訊
Properties props = new Properties();//建立了一個map集合					
props.load(new FileInputStream(properties配置檔案路徑);
		
properties檔案内容
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///資料庫名
username=root
password=root

// 2.通過BasicDataSourceFactory擷取一個連接配接池對象
DataSource ds = BasicDataSourceFactory.createDataSource(props);
           

C3p0連接配接池

C3P0是一個開源的JDBC連接配接池,它實作了資料源和JNDI綁定,支援JDBC3規範和JDBC2的标準擴充。目前使用它的開源項目有Hibernate,Spring等。

c3p0與dbcp差別

dbcp沒有自動回收空閑連接配接的功能

c3p0有自動回收空閑連接配接功能

在使用c3p0連接配接池時将c3p0的jar 複制WEB-INF/lib下,我們使用的版本

c3p0-0.9.1.2.jar

c3p0連接配接池編碼實作

ComboPooledDataSource ds = new ComboPooledDataSource();
// 2.手動配置參數
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql:///day13");
ds.setUser("root");
ds.setPassword("abc");
           

c3p0連接配接池配置檔案實作

隻要在src下建立c3p0.properties or c3p0-config.xml名稱的配置檔案,c3p0會自動查找.
ComboPooledDataSource ds = new ComboPooledDataSource();
自動查找配置檔案
在src/c3p0-config.xml
<c3p0-config>
	<default-config>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql:///資料庫名</property>
		<property name="user">root</property>
		<property name="password">abc</property>
	</default-config>
</c3p0-config>
           

連接配接池的工具類

public class DataSourceUtils {

	private static ComboPooledDataSource cpds = new ComboPooledDataSource();//自動去加載c3p0-config.xml配置檔案讀取資料庫連接配接相關資訊
	//擷取連接配接對象,從連接配接池中傳回一個連接配接對象
	public static Connection getConnection() throws SQLException {
		return cpds.getConnection();
		
	}
	//擷取連接配接池對象
	public static DataSource getDataSource() {
		return cpds;
	}

}
           

繼續閱讀