1. 程式人生 > 其它 >JDBC的兩種開源的資料庫連線池

JDBC的兩種開源的資料庫連線池

JDBC 的資料庫連線池使用 javax.sql.DataSource 來表示,DataSource 只是一個介面,該介面通常由伺服器(Weblogic, WebSphere, Tomcat)提供實現,也有一些開源組織提供實現:

1、DBCP 資料庫連線池

2、C3P0 資料庫連線池

DataSource 通常被稱為資料來源,它包含連線池和連線池管理兩個部分,習慣上也經常把 DataSource 稱為連線池

1、DBCP資料來源

DBCP 是 Apache 軟體基金組織下的開源連線池實現,該連線池依賴該組織下的另一個開源系統:Common-pool. 如需使用該連線池實現,應在系統中增加如下兩個 jar 檔案:

1)Commons-dbcp.jar:連線池的實現

2)Commons-pool.jar:連線池實現的依賴庫

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

注意:

資料來源和資料庫連線不同,資料來源無需建立多個,它是產生資料庫連線的工廠,因此整個應用只需要一個數據源即可。

當資料庫訪問結束後,程式還是像以前一樣關閉資料庫連線:conn.close(); 但conn.close()並沒有關閉資料庫的物理連線,它僅僅把資料庫連線釋放,歸還給了資料庫連線池。

方式一:

示例程式碼:

步驟:

1、加入兩個jar

DBCP資料庫連線池的的jar:Commons-dbcp.jar

連線池實現的依賴庫:Commons-pool.jar,如果不加這個,執行報如下異常

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/pool/KeyedObjectPoolFactory
at com.jdbc.datasource.TestDBCP.main(TestDBCP.java:14)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool.KeyedObjectPoolFactory
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more

2、編寫程式碼

package com.jdbc.datasource;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.commons.dbcp.BasicDataSource;

public class TestDBCP {

public static void main(String[] args) throws SQLException {
//1.建立DBCP資料來源(即連線池)
BasicDataSource ds = new BasicDataSource();

//2.設定資料來源的必須屬性
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/test");
ds.setUsername("root");
ds.setPassword("root");

//3.設定資料來源的可選屬性
//(1)指定資料庫連線池中初始化連線數的個數
ds.setInitialSize(10);

//(2)指定最大的連線數: 同一時刻可以同時向資料庫申請的連線數
ds.setMaxActive(50);

//(3)在資料庫連線池中儲存的最少的空閒連線的數量
ds.setMinIdle(2);

//(4)等待資料庫連線池分配連線的最長時間. 單位為毫秒. 超出該時間將丟擲異常.
ds.setMaxWait(1000*5);

//4.從資料來源中獲取資料庫連線
Connection conn = ds.getConnection();
System.out.println(conn);
}
}

測試超過連線數

 

package com.jdbc.datasource;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.commons.dbcp.BasicDataSource;

public class TestDBCP2 {

public static void main(String[] args) throws SQLException {
//1.建立DBCP資料來源(即連線池)
BasicDataSource ds = new BasicDataSource();

//2.設定資料來源的必須屬性
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/test");
ds.setUsername("root");
ds.setPassword("root");

//3.設定資料來源的可選屬性
//(1)指定資料庫連線池中初始化連線數的個數
ds.setInitialSize(3);

//(2)指定最大的連線數: 同一時刻可以同時向資料庫申請的連線數
ds.setMaxActive(5);

//(3)指定最小活躍的連線數: 在資料庫連線池中儲存的最少的空閒連線的數量
ds.setMinIdle(2);

//(4)等待資料庫連線池分配連線的最長時間. 單位為毫秒. 超出該時間將丟擲異常.
ds.setMaxWait(1000*5);

//4.從資料來源中獲取資料庫連線
for(int i=0;i<6;i++){
Connection conn = ds.getConnection();
System.out.println("獲取第"+(i+1)+"個"+conn);
//這裡沒有關閉,即沒有放回連線池
}
}
}

測試如果連線重複使用

 

package com.jdbc.datasource;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.commons.dbcp.BasicDataSource;

public class TestDBCP3 {

public static void main(String[] args) throws SQLException {
//1.建立DBCP資料來源(即連線池)
BasicDataSource ds = new BasicDataSource();

//2.設定資料來源的必須屬性
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/test");
ds.setUsername("root");
ds.setPassword("root");

//3.設定資料來源的可選屬性
//(1)指定資料庫連線池中初始化連線數的個數
ds.setInitialSize(3);

//(2)指定最大的連線數: 同一時刻可以同時向資料庫申請的連線數
ds.setMaxActive(5);

//(3)指定最小活躍的連線數: 在資料庫連線池中儲存的最少的空閒連線的數量
ds.setMinIdle(2);

//(4)等待資料庫連線池分配連線的最長時間. 單位為毫秒. 超出該時間將丟擲異常.
ds.setMaxWait(1000*5);

//4.從資料來源中獲取資料庫連線
for(int i=0;i<10;i++){
new Thread(){
public void run(){
try {
Connection conn = ds.getConnection();
System.out.println("獲取1個"+conn);

Thread.sleep(3000);

//隔3秒換回去
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();

}
}
}

方式二:

優化程式碼:

直接使用BasicDataSource,耦合,而且在程式碼中需要很多setXxx()設定屬性值

使用dbcp.properties屬性配置檔案和BasicDataSourceFactory更靈活

步驟:

1. 載入 dbcp 的 properties 配置檔案: 配置檔案中的鍵需要來自 BasicDataSource的屬性.

2. 呼叫 BasicDataSourceFactory 的 createDataSource 方法建立 DataSource例項

3. 從 DataSource 例項中獲取資料庫連線.

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=root
initialSize=3
maxActive=5
minIdle=2
maxWait=5000
package com.jdbc.datasource;

import java.sql.Connection;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

public class TestDBCP3 {

public static void main(String[] args) throws Exception {
//1.獲取配置檔案資訊
//注意:配置檔案中的key來自BasicDataSourceFactory的屬性(set方法後面單詞首字母改小寫即可)
Properties pro = new Properties();
pro.load(ClassLoader.getSystemResourceAsStream("dbcp.properties"));

//2.建立DBCP資料來源(即連線池)
DataSource ds = BasicDataSourceFactory.createDataSource(pro);

//3.從資料來源中獲取資料庫連線
Connection conn = ds.getConnection();
System.out.println("獲取1個"+conn);
}
}

JDBCUtils修改DBCP版:

package com.atguigu.utils;

import java.sql.Connection;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

public class DBCPUtils {
private static Properties pro = new Properties();
private static DataSource ds ;

static{
try {
//載入,讀取jdbc.properties配置的資訊
pro.load(ClassLoader.getSystemClassLoader().getResourceAsStream("dbcp.properties"));

//建立池子
ds = BasicDataSourceFactory.createDataSource(pro);
} catch (Exception e) {
e.printStackTrace();
}
}

public static Connection getConnection()throws Exception{
return ds.getConnection();
}

}

 

2、C3P0資料來源

C3P0是一個開源的JDBC連線池,它實現了資料來源和JNDI繫結,java培訓支援JDBC3規範和JDBC2的標準擴充套件。目前使用它的開源專案有Hibernate,Spring等。

c3p0與dbcp區別

dbcp沒有自動回收空閒連線的功能

c3p0有自動回收空閒連線功能

方式一:

 

 

步驟:

1、加入jar

如果是c3p0-0.9.1.2版本,加入一個jar即可c3p0-0.9.1.2.jar

如果是c3p0-0.9.2之後的版本,需要加入兩個jar:c3p0-0.9.X.jar和
mchange-commons-java-XX.jar

2、編寫程式碼

package com.jdbc.datasource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class TestC3P0 {
public static void main(String[] args)throws Exception {
//1、建立c3p0資料來源物件
ComboPooledDataSource ds = new ComboPooledDataSource();
//2、設定必須屬性
ds.setDriverClass( "com.mysql.jdbc.Driver" );
ds.setJdbcUrl( "jdbc:mysql://localhost:3306/test" );
ds.setUser("root");
ds.setPassword("root");

//3、獲取連線
System.out.println(ds.getConnection());
}
}

方式二:

 

 

 

 

 

步驟:

1. 在src目錄建立 c3p0-config.xml 檔案, 參考幫助文件中 Appendix B: Configuation Files 的內容

2. 建立 ComboPooledDataSource 例項;

DataSource dataSource = new ComboPooledDataSource("helloc3p0");

3. 從 DataSource 例項中獲取資料庫連線.

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>

<named-config name="helloc3p0">[I1]

<!-- 指定連線資料來源的基本屬性 -->
<property name="user">root</property>
<property name="password">root</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>

<!-- 若資料庫中連線數不足時, 一次向資料庫伺服器申請多少個連線 -->
<property name="acquireIncrement">5</property>
<!-- 初始化資料庫連線池時連線的數量 -->
<property name="initialPoolSize">5</property>
<!-- 資料庫連線池中的最小的資料庫連線數 -->
<property name="minPoolSize">5</property>
<!-- 資料庫連線池中的最大的資料庫連線數 -->
<property name="maxPoolSize">10</property>
</named-config>

</c3p0-config>
package com.jdbc.datasource;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class TestC3P02 {
public static void main(String[] args)throws Exception {
DataSource dataSource = new ComboPooledDataSource("helloc3p0");
System.out.println(dataSource.getConnection());
}
}

JDBCUtils修改成c3p0版

package com.atguigu.utils;

import java.sql.Connection;
import java.sql.SQLException;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3p0Utils {
//建立資料來源,用的是c3p0-config.xml檔案中<default-config>
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();

//獲取資料來源物件
public static ComboPooledDataSource getDataSource() {
return dataSource;
}

//獲取連線
public static Connection getConnection() throws SQLException{
return dataSource.getConnection();
}
}

如果只有一個配置,那麼可以使用<default-config></default-config>,代替<name-config name=””> </named-config>

這樣在new ComboPooledDataSource()就可以使用無參構造了。