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,基本配置

注:在Druid連接池的配置中,driverClassName可配可不配,如果不配置會根據url自動識別dbType(數據庫類型),然后選擇相應的driverClassName。
2,關鍵配置
注1:在DBCP連接池的配置中,還有一個maxIdle的屬性,表示最大空閑連接數,超過的空閑連接將被釋放,默認值為8。對應的該屬性在Druid連接池已不再使用,配置了也沒有效果,c3p0連接池則沒有對應的屬性。
3,性能配置
(1)預緩存設置:

(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 屬性說明表