DBCP、c3p0、Druid三大連線池區別
DBCP、c3p0、Druid三大連線池區別
一、連線池優勢
如果一個專案中如果需要多個連線,如果一直獲取連線,斷開連線,這樣比較浪費資源;
如果建立一個池,用池來管理Connection,這樣就可以重複使用Connection。
有了池我們就不用自己來建立Connection,而是通過池來獲取Connection物件。當使用完Connection後,呼叫Connection的close()方法也不會真的關閉Connection,而是把Connection“歸還”給池。
池就可以再利用這個Connection物件了。這裡我們常用的連線池有三種,分別是:DBCP連線池、C3P0連線池和DRUID連線池;
二、DBCP連線池
DBCP是一個依賴Jakarta commons-pool物件池機制的資料庫連線池.DBCP可以直接的在應用程式中使用,Tomcat的資料來源使用的就是DBCP;
使用連線池的第一項工作就是導包,這裡需要的兩個jar包分別是:
在使用寫連線池工具類的時候,可以通過配置檔案來連線資料庫,配置檔案中記錄了連線資料庫的驅動、URL、使用者名稱和密碼等資訊;但要注意這裡的檔案字尾為:“.properties”。
把通過配置檔案連線資料庫的部分寫在靜態程式碼塊中,隨著類的載入只加載一次。出了連線資料庫,還要提供一個獲得資料來源的方法和一個獲取連線的方法;
下邊是把連線池寫成一個工具類的程式碼,寫成工具類和直接使用的程式碼幾乎相同,就不在重複的寫了。
配置檔案的部分內容:
程式碼:(配置檔案的命名為:dbcp.properties)
public class DBCPUtils { //首先定義私有的datasource private static DataSource datasource; //把配置檔案部分放在靜態程式碼塊中,呼叫時直接載入 static{ try { //載入檔案 InputStream is=DBCPUtils.class.getClassLoader().getResourceAsStream("dbcp.properties");//例項化properties集合 Properties prop=new Properties(); prop.load(is); //首先載入核心類 datasource=BasicDataSourceFactory.createDataSource(prop); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //提供獲得資料來源 public static DataSource getDataSource(){ return datasource; } //提供獲得連線 public static Connection getConnection() throws SQLException{ return datasource.getConnection(); } }
在寫成工具類後都要對外提供一個數據源DateSource和一個連線Connection。作用是,如果我們在進行資料庫操作的時候要是使用DBUtils類的時候,就要使用QueryRunner核心類,而這個類在進行與資料庫連線的時候只要一句程式碼:QueryRunner qr=newQueryRunner(資料來源);
通過連線池獲得:DBCPUtils.getDataSource()獲得。如果不使用DBUtils工具類,我們就可以直接通過DBCPUtils .getConnection()來直接獲得連線。
三、C3P0連線池
c3p0是一個開放原始碼的JDBC連線池,它在lib目錄中與Hibernate一起釋出,包括了實現jdbc3和jdbc2擴充套件規範說明的Connection 和Statement 池的DataSources 物件。
使用連線池的第一項工作就是導包,這裡需要的兩個jar包分別是:
這種連線池在進行資料庫的連線的時候有兩種連線方法:使用配置檔案和不使用配置檔案兩種。
當然使用配置檔案的時候程式碼要簡介的多,配置檔案中同樣是記錄了連線資料庫的驅動、URL、使用者名稱和密碼等資訊。
(1)不使用配置檔案的程式碼:三個步驟:
<1>、匯入核心類:ComboPooledDataSource
<2>、基本的四項設定,也就是設定驅動,URL,使用者名稱和密碼等四項。
<3>、其他四項。程式碼如下:
public class c3p0_test01 { public static void main(String[] args) throws Exception { //匯入一個核心類 ComboPooledDataSource dataSource = new ComboPooledDataSource(); //基本四項設定 dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/eeday09"); dataSource.setUser("root"); dataSource.setPassword("123"); //其他四項設定 dataSource.setInitialPoolSize(10); //初始化連線個數 dataSource.setMaxPoolSize(40); //最大連結數 dataSource.setMinPoolSize(5); //設定最小連結數 dataSource.setAcquireIncrement(2); //設定每次增加的連線數 Connection conn=dataSource.getConnection(); //進行資料庫連線 System.out.println(conn); } }
(2)如果使用配置檔案連線資料庫,其中配置檔案中的內容為:
使用配置檔案進行連線的寫法如下:
import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import org.apache.commons.dbutils.QueryRunner; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0Utils { //1、提供私有化的資料來源 使用預設設定 private static ComboPooledDataSource datasource=new ComboPooledDataSource(); //使用命名配置 //private static ComboPooledDataSource datasource =new ComboPooledDataSource("itheima"); //2.提供對外的資料來源 public static DataSource getDataSource(){ return datasource; } //3.提供對外的連結 public static Connection getConnection() throws SQLException{ return datasource.getConnection(); } }
在寫成工具類後都要對外提供一個數據源DateSource和一個連線Connection。作用是,如果我們在進行資料庫操作的時候要是使用DBUtils類的時候,就要使用QueryRunner核心類,而這個類在進行與資料庫連線的時候只要一句程式碼:QueryRunner qr=newQueryRunner(資料來源);
我們可以通過連線池獲得:C3P0Utils.getDataSource() 獲得。如果不使用DBUtils工具類,我們就可以直接通過C3P0Utils.getConnection()來直接獲得連線。
四、Druid連線池
Druid首先是一個數據庫連線池。Druid是目前最好的資料庫連線池,在功能、效能、擴充套件性方面,都超過其他資料庫連線池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已經在阿里巴巴部署了超過600個應用,經過一年多生產環境大規模部署的嚴苛考驗。
它不僅僅是一個數據庫連線池,它還包含一個ProxyDriver,一系列內建的JDBC元件庫,一個 SQL Parser。支援所有JDBC相容的資料庫,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等等。Druid針對Oracle和MySql做了特別優化,比如Oracle的PS Cache記憶體佔用優化,MySql的ping檢測優化。Druid提供了MySql、Oracle、Postgresql、SQL-92的SQL的完整支援,這是一個手寫的高效能SQL Parser,支援Visitor模式,使得分析SQL的抽象語法樹很方便。簡單SQL語句用時10微秒以內,複雜SQL用時30微秒。通過Druid提供的SQL Parser可以在JDBC層攔截SQL做相應處理,比如說分庫分表、審計等。Druid防禦SQL注入攻擊的WallFilter就是通過Druid的SQL Parser分析語義實現的。
使用步驟:
1,使用連線池的第一項工作就是導包,這裡需要的jar包分別是:druid-1.1.4.jar 1.1.4
2,druid.properties 檔案內容:
# 配置資料庫的連線引數 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/test username=root password=root # 配置連線池的引數 initialSize=5 maxActive=10 maxWait=3000 maxIdle=6 minIdle=3
3,連線池工具類:
/** 1)建立私有靜態資料來源成員變數DataSource ds 2)在靜態程式碼塊中建立連線池 a)建立屬性物件 b)從類路徑下載入屬性檔案,得到輸入流物件 c)通過工廠類建立一個數據源 3)建立公有的得到資料來源的方法getDataSource() 4)建立得到連線物件的方法 getConnection() 5)建立釋放資源的方法 close() */ /** * 連線池的工具類 */ public class DataSourceUtils { //建立一個成員變數 private static DataSource ds; /** * 載入的程式碼寫在靜態程式碼塊中 */ static { try { Properties info = new Properties(); //載入類路徑下,即src目錄下的druid.properties這個檔案 info.load(DataSourceUtils.class.getResourceAsStream("/druid.properties")); //讀取屬性檔案建立連線池 ds = DruidDataSourceFactory.createDataSource(info); } catch (Exception e) { e.printStackTrace(); } } /** * 得到資料來源 */ public static DataSource getDataSource() { return ds; } /** * 得到連線物件 */ public static Connection getConnection() { try { return ds.getConnection(); } catch (SQLException e) { throw new RuntimeException(e); } } /** * 釋放資源 */ public static void close(Connection conn, Statement stmt, ResultSet rs) { if (rs!=null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt!=null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close(Connection conn, Statement stmt) { close(conn, stmt, null); } }
4,資料來源工具類的使用:
public class DemoAdd { public static void main(String[] args) { //1. 建立連線物件,通過連線池工具類 Connection conn = null; PreparedStatement ps = null; int row = 0; try { conn = DataSourceUtils.getConnection(); //2. 建立語句物件 ps = conn.prepareStatement("INSERT INTO student values(null,?,?,?)"); ps.setString(1,"張遼"); ps.setInt(2,1); ps.setString(3,"194-06-16"); //3. 使用executeUpdate()寫入到資料庫 row = ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { //4. 釋放資源 DataSourceUtils.close(conn, ps); } System.out.println("添加了" + row); } }
五、三者區別
我們從連線池配置的基本配置、關鍵配置、效能配置等主要配置來分析:
1,基本配置
基本配置是指連線池進行資料庫連線的四個基本必需配置: 傳遞給JDBC驅動的用於連線資料庫的使用者名稱、密碼、URL以及驅動類名。注:在Druid連線池的配置中,driverClassName可配可不配,如果不配置會根據url自動識別dbType(資料庫型別),然後選擇相應的driverClassName。
2,關鍵配置
為了發揮資料庫連線池的作用,在初始化時將建立一定數量的資料庫連線放到連線池中,這些資料庫連線的數量是由最小資料庫連線數來設定的。無論這些數 據庫連線是否被使用,連線池都將一直保證至少擁有這麼多的連線數量。連線池的最大資料庫連線數量限定了這個連線池能佔有的最大連線數,當應用程式向連線池 請求的連線數超過最大連線數量時,這些請求將被加入到等待佇列中。 最小連線數:是資料庫一直保持的資料庫連線數,所以如果應用程式對資料庫連線的使用量不大,將有大量的資料庫資源被浪費。 初始化連線數:連線池啟動時建立的初始化資料庫連線數量。 最大連線數:是連線池能申請的最大連線數,如果資料庫連線請求超過此數,後面的資料庫連線請求被加入到等待佇列中。 最大等待時間:當沒有可用連線時,連線池等待連線被歸還的最大時間,超過時間則丟擲異常,可設定引數為0或者負數使得無限等待(根據不同連線池配置)。
注1:在DBCP連線池的配置中,還有一個maxIdle的屬性,表示最大空閒連線數,超過的空閒連線將被釋放,預設值為8。對應的該屬性在Druid連線池已不再使用,配置了也沒有效果,c3p0連線池則沒有對應的屬性。
注2:資料庫連線池在初始化的時候會建立initialSize個連線,當有資料庫操作時,會從池中取出一個連線。如果當前池中正在使用的連線數等 於maxActive,則會等待一段時間,等待其他操作釋放掉某一個連線,如果這個等待時間超過了maxWait,則會報錯;如果當前正在使用的連線數沒 有達到maxActive,則判斷當前是否空閒連線,如果有則直接使用空閒連線,如果沒有則新建立一個連線。在連線使用完畢後,不是將其物理連線關閉,而 是將其放入池中等待其他操作複用。3,效能配置
(1)預快取設定:
即是PSCache,PSCache對支援遊標的資料庫效能提升巨大,比如說oracle。JDBC的標準引數,用以控制資料來源內載入的 PreparedStatements數量。但由於預快取的statements屬於單個connection而不是整個連線池,所以設定這個引數需要考 慮到多方面的因素。 單個連線擁有的最大快取數:要啟用PSCache,必須配置大於0,當大於0時,poolPreparedStatements自動觸發修改為true。在Druid中,不會存在Oracle下PSCache佔用記憶體過多的問題,可以把這個數值配置大一些,比如說100(2)連線有效性檢測設定:
連線池內部有機制判斷,如果當前的總的連線數少於miniIdle,則會建立新的空閒連線,以保證連線數得到miniIdle。如果當前連線池中某 個連線在空閒了timeBetweenEvictionRunsMillis時間後任然沒有使用,則被物理性的關閉掉。有些資料庫連線的時候有超時限制 (mysql連線在8小時後斷開),或者由於網路中斷等原因,連線池的連線會出現失效的情況,這時候設定一個testWhileIdle引數為true, 可以保證連線池內部定時檢測連線的可用性,不可用的連線會被拋棄或者重建,最大情況的保證從連線池中得到的Connection物件是可用的。當然,為了 保證絕對的可用性,你也可以使用testOnBorrow為true(即在獲取Connection物件時檢測其可用性),不過這樣會影響效能。
(3)超時連線關閉設定:
removeAbandoned引數,用來檢測到當前使用的連線是否發生了連線洩露,所以在程式碼內部就假定如果一個連線建立連線的時間很長,則將其認定為洩露,繼而強制將其關閉掉。
(4)c3p0重連設定:
設定獲取連線失敗後,是否重新連線以及間隔時間。
六、DBCP、C3P0、DRUID三大連線池屬性說明表
1,DBCP 屬性說明表
2,C3P0 屬性說明表
(3)DRUID 屬性說明表