JDBC : 資料庫連接池,jdbc資料庫連接池
所需工具
commons-pool2-2.3.jar : 串連池實現的依賴庫
commons-dbcp2-2.0.1.jar : 串連池的實現
c3p0-0.9.2.1.jar
如果使用 c3p0 出現Method‘initializationError’not found,opening the test class,再添加
mchange-commons-java-0.2.3.4.jar包
所使用的JDBC驅動 ojdbc6.jar
一、JDBC資料庫連接池的必要性
在使用開發基於資料庫的web程式時,傳統的模式基本是按以下步驟:
-在主程式(如servlet、beans)中建立資料庫連接。
-進行sql操作
-斷開資料庫連接。
這種模式開發,存在的問題:
普通的JDBC資料庫連接使用 DriverManager 來擷取,每次向資料庫建立串連的時候都要將 Connection 載入到記憶體中,再驗證使用者名稱和密碼(得花費0.05s~1s的時間)。需要資料庫連接的時候,就向資料庫要求一個,執行完成後再中斷連線。這樣的方式將會消耗大量的資源和時間。資料庫的串連資源並沒有得到很好的重複利用.若同時有幾百人甚至幾千人線上,頻繁的進行資料庫連接操作將佔用很多的系統資源,嚴重的甚至會造成伺服器的崩潰。
對於每一次資料庫連接,使用完後都得斷開。否則,如果程式出現異常而未能關閉,將會導致資料庫系統中的記憶體流失,最終將導致重啟資料庫。
這種開發不能控制被建立的連線物件數,系統資源會被毫無顧及的分配出去,如串連過多,也可能導致記憶體流失,伺服器崩潰。
資料庫連接池(connection pool)
為解決傳統開發中的資料庫連接問題,可以採用資料庫連接池技術。
資料庫連接池的基本思想就是為資料庫連接建立一個“緩衝池”。預先在緩衝池中放入一定數量的串連,當需要建立資料庫連接時,只需從“緩衝池”中取出一個,使用完畢之後再放回去。
資料庫連接池負責分配、管理和釋放資料庫連接,它允許應用程式重複使用一個現有的資料庫連接,而不是重建立立一個。
資料庫連接池在初始化時將建立一定數量的資料庫連接放到串連池中,這些資料庫連接的數量是由最小資料庫連接數來設定的。無論這些資料庫連接是否被使用,串連池都將一直保證至少擁有這麼多的串連數量。串連池的最大資料庫連接數量限定了這個串連池能佔有的最大串連數,當應用程式向串連池請求的串連數超過最大串連數量時,這些請求將被加入到等待隊列中。
資料庫連接池的工作原理
兩種開源的資料庫連接池
JDBC 的資料庫連接池使用 javax.sql.DataSource 來表示,DataSource 只是一個介面,該介面通常由伺服器(Weblogic, WebSphere, Tomcat)提供實現,也有一些開源組織提供實現:
DBCP 資料庫連接池
C3P0 資料庫連接池
DataSource 通常被稱為資料來源,它包含串連池和串連池管理兩個部分,習慣上也經常把 DataSource 稱為串連池
DBCP資料來源
@Test//OKpublic void testDBCPWithBasicDataSource() throws Exception {BasicDataSource dataSource = null;//建立資料來源執行個體dataSource = new BasicDataSource();//設定基本屬性dataSource.setUsername("scott");dataSource.setPassword("qiaolezi");dataSource.setUrl("jdbc:oracle:thin:@localhost:1521:orcl");dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");//其他屬性//設定資料庫的初始串連數dataSource.setInitialSize(5);//最大空閑串連數dataSource.setMaxIdle(8);//最大串連數dataSource.setMaxTotal(20);//設定資料庫中最少有2個空閑串連,在資料庫連接池中儲存的最少的空閑串連的數量dataSource.setMinIdle(2);/* 擷取串連時的最大等待毫秒數(如果設定為阻塞時BlockWhenExhausted),如果逾時就拋異常, 小於零:阻塞不確定的時間, 預設-1 */dataSource.setMaxWaitMillis(1000*6);//是否啟用後進先出, 預設truedataSource.setLifo(true);//在擷取串連的時候檢查有效性, 預設falsedataSource.setTestOnBorrow(false);//在空閑時檢查有效性, 預設falsedataSource.setTestWhileIdle(false);//逐出串連的最小空閑時間 預設1800000毫秒(30分鐘)dataSource.setMinEvictableIdleTimeMillis(1800000);/*對象空閑多久後逐出, 當空閑時間>該值 且 空閑串連>最大空閑數 時直接逐出,不再根據MinEvictableIdleTimeMillis判斷 (預設逐出策略) */dataSource.setSoftMinEvictableIdleTimeMillis(1800000);//逐出掃描的時間間隔(毫秒) 如果為負數,則不運行逐出線程, 預設-1dataSource.setTimeBetweenEvictionRunsMillis(-1);Connection conn = dataSource.getConnection();System.out.println(conn);}
PS:資料來源和資料庫連接不同,資料來源無需建立多個,它是產生資料庫連接的工廠,因此整個應用只需要一個資料來源即可。
當資料庫訪問結束後,程式還是像以前一樣關閉資料庫連接:conn.close(); 但上面的代碼並沒有關閉資料庫的物理串連,它僅僅把資料庫連接釋放,歸還給了資料庫連接池。
/** * 1. 載入 dbcp 的properties 設定檔: 鍵(來自BasicDataSource的屬性) * 2. 調用 BasicDataSourceFactory 的createDataSource(properties)方法得到 DataSource執行個體 * 3. 從 DataSource 執行個體中擷取資料庫連接 * @throws Exception */@Test//okpublic void testDBCPWithDataSourceFactory()throws Exception{Properties properties = new Properties();InputStream inStream = JDBC_Tools.class.getClassLoader().getResourceAsStream("dbcp.properties");properties.load(inStream);DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);System.out.println(dataSource.getConnection());//測試BasicDataSource basicDataSource = (BasicDataSource) dataSource;System.out.println(basicDataSource.getMaxWaitMillis());}
DBCP.properties
username=scottpassword=qiaolezidriverClassName=oracle.jdbc.driver.OracleDriverurl=jdbc:oracle:thin:@localhost:1521:orclinitialSize=5minIdle=5maxWaitMillis=5000
注意鍵要符合javabean
C3P0 資料來源
@Testpublic void testc3p0() throws Exception {ComboPooledDataSource cpds = new ComboPooledDataSource();cpds.setDriverClass( "oracle.jdbc.driver.OracleDriver" ); cpds.setJdbcUrl( "jdbc:oracle:thin:@localhost:1521:orcl" );cpds.setUser("scott"); cpds.setPassword("qiaolezi"); System.out.println(cpds.getConnection());}
使用ComboPooledDataSource
/** * 1.建立 c3p0-config.xml ,參考 c3p0-0.9.2.1\doc index.html 協助文檔Appendix A: Configuration Properties * 2.建立DataSource dataSource = ComboPooledDataSource("helloc3p0"); 執行個體 * 3. 從DataSource 執行個體中擷取資料庫連接 * @throws Exception */@Test//OKpublic void testC3P0WithConfig() throws Exception{DataSource dataSource = new ComboPooledDataSource("helloc3p0"); //xml 的 <named-config name="helloc3p0"> System.out.println(dataSource);System.out.println(dataSource.getConnection());ComboPooledDataSource com = (ComboPooledDataSource) dataSource;System.out.println(com.getMaxStatements());}
c3p0-config.XML
<c3p0-config> <named-config name="helloc3p0"> <!-- 指定串連資料來源的基本屬性 --> <property name="user">scott</property> <property name="passwword">qiaolezi</property> <property name="driverClass">oracle.jdbc.driver.OracleDriver</property> <property name="jdbcUrl">jdbc:oracle:thin:@localhost:1521:orcl</property> <!-- 若資料庫中串連數不足時,一次向資料庫伺服器申請多少個串連 --> <property name="acquireIncrement">50</property> <!-- 初始化資料庫連接池時串連的數量 --> <property name="initialPoolSize">100</property> <!-- 資料庫連接池中最小的資料庫連接數 --> <property name="minPoolSize">50</property> <!-- 資料庫連接池中最大的資料庫連接數 --> <property name="maxPoolSize">1000</property> <!-- 資料庫連接池可以維護的Statement 的個數 --> <property name="maxStatements">0</property> <!-- 每個串連同時可以使用的 Statement 對象的個數 --> <property name="maxStatementsPerConnection">5</property> </named-config></c3p0-config>
最後就可以進行JDBC_tools工具類中getConnection()方法的重載,以後的Connection.close().並不是關閉串連,而是將使用後的資料庫連接返還給資料庫連接池