JAVA之JDBC數據庫鏈接池總結篇

JDBC數據庫鏈接池

 

1、JDBC數據庫鏈接池的必要性

一、在使用開發基於數據庫的web程序時,傳統的模式基本是按如下步驟:java

(1)在主程序(如servlet、beans)中創建數據庫鏈接
(2)進行sql操做
(3)斷開數據庫鏈接python

二、這種模式開發,存在的問題:mysql

(1)普通的JDBC數據庫鏈接使用 DriverManager 來獲取,每次向數據庫創建鏈接的時候都要將 Connection加載到內存中,再驗證用戶名和密碼(得花費0.05s~1s的時間)。須要數據庫鏈接的時候,就向數據庫要求一個,執行完成後再斷開鏈接。這樣的方式將會消耗大量的資源和時間。數據庫的鏈接資源並無獲得很好的重複利用。若同時有幾百人甚至幾千人在線,頻繁的進行數據庫鏈接操做將佔用不少的系統資源,嚴重的甚至會形成服務器的崩潰。
(2)對於每一次數據庫鏈接,使用完後都得斷開。不然,若是程序出現異常而未能關閉,將會致使數據庫系統中的內存泄漏,最終將致使重啓數據庫。(回憶:何爲Java的內存泄漏?)
(3)這種開發不能控制被建立的鏈接對象數,系統資源會被毫無顧及的分配出去,如鏈接過多,也可能致使內存泄漏,服務器崩潰。LIK1web

2、數據庫鏈接池技術

爲解決傳統開發中的數據庫鏈接問題,能夠採用數據庫鏈接池技術。sql

一、數據庫鏈接池的基本思想
就是爲數據庫鏈接創建一個「緩衝池」。預先在緩衝池中放入必定數量的鏈接,當須要創建數據庫鏈接時,只需從「緩衝池」中取出一個,使用完畢以後再放回去。數據庫

數據庫鏈接池負責分配管理釋放數據庫鏈接,它容許應用程序重複使用一個現有的數據庫鏈接,而不是從新創建一個tomcat

數據庫鏈接池在初始化時將建立必定數量的數據庫鏈接放到鏈接池中,這些數據庫鏈接的數量是由最小數據庫鏈接數來設定的。不管這些數據庫鏈接是否被使用,鏈接池都將一直保證至少擁有這麼多的鏈接數量。鏈接池的最大數據庫鏈接數量限定了這個鏈接池能佔有的最大鏈接數,當應用程序向鏈接池請求的鏈接數超過最大鏈接數量時,這些請求將被加入到等待隊列中。
在這裏插入圖片描述
二、數據庫鏈接池的工做原理:
在這裏插入圖片描述
三、數據庫鏈接池技術的優勢:服務器

(1)資源重用
因爲數據庫鏈接得以重用,避免了頻繁建立,釋放鏈接引發的大量性能開銷。在減小系統消耗的基礎上,另外一方面也增長了系統運行環境的平穩性。性能

(2)更快的系統反應速度
數據庫鏈接池在初始化過程當中,每每已經建立了若干數據庫鏈接置於鏈接池中備用。此時鏈接的初始化工做均已完成。對於業務請求處理而言,直接利用現有可用鏈接,避免了數據庫鏈接初始化和釋放過程的時間開銷,從而減小了系統的響應時間大數據

(3)新的資源分配手段
對於多應用共享同一數據庫的系統而言,可在應用層經過數據庫鏈接池的配置,實現某一應用最大可用數據庫鏈接數的限制,避免某一應用獨佔全部的數據庫資源

(4)統一的鏈接管理,避免數據庫鏈接泄漏
在較爲完善的數據庫鏈接池實現中,可根據預先的佔用超時設定,強制回收被佔用鏈接,從而避免了常規數據庫鏈接操做中可能出現的資源泄露。LIK2

3、多種開源的數據庫鏈接池

一、JDBC 的數據庫鏈接池使用 javax.sql.DataSource 來表示,DataSource 只是一個接口,該接口一般由服務器(Weblogic, WebSphere, Tomcat)提供實現,也有一些開源組織提供實現:

(1)DBCP 是Apache提供的數據庫鏈接池。tomcat服務器自帶dbcp數據庫鏈接池。速度相對c3p0較快,但因自身存在BUG,Hibernate3已再也不提供支持。

(2)C3P0 是一個開源組織提供的一個數據庫鏈接池,速度相對較慢,穩定性還能夠,hibernate官方推薦使用。

(3)Proxool 是sourceforge下的一個開源項目數據庫鏈接池,有監控鏈接池狀態的功能,穩定性較c3p0差一點.

(4)BoneCP 是一個開源組織提供的數據庫鏈接池,速度快。

(5)Druid 是阿里提供的數據庫鏈接池,聽說是集DBCP 、C3P0 、Proxool優勢於一身的數據庫鏈接池,可是速度不肯定是否有BoneCP快。

二、DataSource 一般被稱爲數據源,它包含鏈接池和鏈接池管理兩個部分,習慣上也常常把 DataSource 稱爲鏈接池

三、DataSource用來取代DriverManager來獲取Connection,獲取速度快,同時能夠大幅度提升數據庫訪問速度。

特別注意

(1)數據源和數據庫鏈接不一樣,數據源無需建立多個,它是產生數據庫鏈接的工廠,所以整個應用只須要一個數據源便可。
(2)當數據庫訪問結束後,程序仍是像之前同樣關閉數據庫鏈接:conn.close();
但conn.close()並無關閉數據庫的物理鏈接,它僅僅把數據庫鏈接釋放,歸還給了數據庫鏈接池。LIK3

3.1 C3P0數據庫鏈接池

(1)獲取鏈接的方式一:

//使用C3P0數據庫鏈接池的方式,獲取數據庫的鏈接:不推薦
public static Connection getConnection1() throws Exception{
	ComboPooledDataSource cpds = new ComboPooledDataSource();
	cpds.setDriverClass("com.mysql.jdbc.Driver"); 
	cpds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
	cpds.setUser("root");
	cpds.setPassword("abc123");
		
// cpds.setMaxPoolSize(100);
	
	Connection conn = cpds.getConnection();
	return conn;
}

(2)獲取鏈接的方式二:

//使用C3P0數據庫鏈接池的配置文件方式,獲取數據庫的鏈接:推薦
private static DataSource cpds = new ComboPooledDataSource("helloc3p0");
public static Connection getConnection2() throws SQLException{
	Connection conn = cpds.getConnection();
	return conn;
}

其中,src下的配置文件爲:(c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<named-config name="helloc3p0">
		<!-- 獲取鏈接的4個基本信息 -->
		<property name="user">root</property>
		<property name="password">abc123</property>
		<property name="jdbcUrl">jdbc:mysql:///test</property>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		
		<!-- 涉及到數據庫鏈接池的管理的相關屬性的設置 -->
		<!-- 若數據庫中鏈接數不足時, 一次向數據庫服務器申請多少個鏈接 -->
		<property name="acquireIncrement">5</property>
		<!-- 初始化數據庫鏈接池時鏈接的數量 -->
		<property name="initialPoolSize">5</property>
		<!-- 數據庫鏈接池中的最小的數據庫鏈接數 -->
		<property name="minPoolSize">5</property>
		<!-- 數據庫鏈接池中的最大的數據庫鏈接數 -->
		<property name="maxPoolSize">10</property>
		<!-- C3P0 數據庫鏈接池能夠維護的 Statement 的個數 -->
		<property name="maxStatements">20</property>
		<!-- 每一個鏈接同時可使用的 Statement 對象的個數 -->
		<property name="maxStatementsPerConnection">5</property>

	</named-config>
</c3p0-config>LIK4

3.2 DBCP數據庫鏈接池

一、DBCP 是 Apache 軟件基金組織下的開源鏈接池實現,該鏈接池依賴該組織下的另外一個開源系統:Common-pool。如需使用該鏈接池實現,應在系統中增長以下兩個 jar 文件:

Commons-dbcp.jar:鏈接池的實現
Commons-pool.jar:鏈接池實現的依賴庫

二、Tomcat 的鏈接池正是採用該鏈接池來實現的。該數據庫鏈接池既能夠與應用服務器整合使用,也可由應用程序獨立使用。

三、數據源和數據庫鏈接不一樣,數據源無需建立多個,它是產生數據庫鏈接的工廠,所以整個應用只須要一個數據源便可。

四、當數據庫訪問結束後,程序仍是像之前同樣關閉數據庫鏈接:conn.close(); 但上面的代碼並無關閉數據庫的物理鏈接,它僅僅把數據庫鏈接釋放,歸還給了數據庫鏈接池

配置屬性說明:
在這裏插入圖片描述
(1)獲取鏈接方式一:

public static Connection getConnection3() throws Exception {
	BasicDataSource source = new BasicDataSource();
		
	source.setDriverClassName("com.mysql.jdbc.Driver");
	source.setUrl("jdbc:mysql:///test");
	source.setUsername("root");
	source.setPassword("abc123");
		
	//
	source.setInitialSize(10);
		
	Connection conn = source.getConnection();
	return conn;
}

(2)獲取鏈接方式二:

//使用dbcp數據庫鏈接池的配置文件方式,獲取數據庫的鏈接:推薦
private static DataSource source = null;
static{
	try {
		Properties pros = new Properties();
		
		InputStream is = DBCPTest.class.getClassLoader().getResourceAsStream("dbcp.properties");
			
		pros.load(is);
		//根據提供的BasicDataSourceFactory建立對應的DataSource對象
		source = BasicDataSourceFactory.createDataSource(pros);
	} catch (Exception e) {
		e.printStackTrace();
	}
		
}
public static Connection getConnection4() throws Exception {
		
	Connection conn = source.getConnection();
	
	return conn;
}

其中,src下的配置文件爲:(dbcp.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true&useServerPrepStmts=false
username=root
password=abc123

initialSize=10
#...LIK5

3.3 Druid(德魯伊)數據庫鏈接池

Druid是阿里巴巴開源平臺上一個數據庫鏈接池實現,它結合了C3P0、DBCP、Proxool等DB池的優勢,同時加入了日誌監控,能夠很好的監控DB池鏈接和SQL的執行狀況,能夠說是針對監控而生的DB鏈接池,能夠說是目前最好的鏈接池之一

import java.sql.Connection;
import java.util.Properties;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

public class TestDruid {
	public static void main(String[] args) throws Exception {
		Properties pro = new Properties();		 pro.load(TestDruid.class.getClassLoader().getResourceAsStream("druid.properties"));
		DataSource ds = DruidDataSourceFactory.createDataSource(pro);
		Connection conn = ds.getConnection();
		System.out.println(conn);
	}
}

其中,src下的配置文件爲:(druid.properties

url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
username=root
password=123456
driverClassName=com.mysql.jdbc.Driver

initialSize=10
maxActive=20
maxWait=1000
filters=wall

詳細參數配置:
在這裏插入圖片描述
在這裏插入圖片描述

相關文章
相關標籤/搜索