用戶每次請求都需要向資料庫獲得鏈接,而資料庫創建連接通常需要消耗相對較大的資源,創建時間也 較長,假設網站一天10萬訪問量,資料庫服務器就需要創建10萬次連接,極大的浪費資料庫的資源,并 且極易造成資料庫服務器記憶體溢位、拓機,
資料庫連接池的基本概念
資料庫連接是一種關鍵的有限的昂貴的資源,這一點在多用戶的網頁應用程式中體現的尤為突出.對資料庫 連接的管理能顯著影響到整個應用程式的伸縮性和健壯性,影響到程式的性能指標.資料庫連接池正式針對 這個問題提出來的.資料庫連接池負責分配,管理和釋放資料庫連接,它允許應用程式重復使用一個現有的 資料庫連接,而不是重新建立一個,
資料庫連接池在初始化時將創建一定數量的資料庫連接放到連接池中, 這些資料庫連接的數量是由最小數 據庫連接數來設定的.無論這些資料庫連接是否被使用,連接池都將一直保證至少擁有這么多的連接數量. 連接池的最大資料庫連接數量限定了這個連接池能占有的最大連接數,當應用程式向連接池請求的連接數 超過最大連接數量時,這些請求將被加入到等待佇列中.
資料庫連接池的最小連接數和最大連接數的設定要考慮到以下幾個因素:
- 最小連接數:是連接池一直保持的資料庫連接,所以如果應用程式對資料庫連接的使用量不大,將會有 大量的資料庫連接資源被浪費.
- 最大連接數:是連接池能申請的最大連接數,如果資料庫連接請求超過次數,后面的資料庫連接請求將 被加入到等待佇列中,這會影響以后的資料庫操作
- 如果最小連接數與最大連接數相差很大:那么最先連接請求將會獲利,之后超過最小連接數量的連接 請求等價于建立一個新的資料庫連接.不過,這些大于最小連接數的資料庫連接在使用完不會馬上被 釋放,他將被放到連接池中等待重復使用或是空間超時后被釋放.
撰寫連接池需實作java.sql.DataSource介面,
開源資料庫連接池
現在很多WEB服務器(Weblogic, WebSphere, Tomcat)都提供了DataSoruce的實作,即連接池的實作, 通常我們把DataSource的實作,按其英文含義稱之為資料源,資料源中都包含了資料庫連接池的實 現,
也有一些開源組織提供了資料源的獨立實作:
- DBCP 資料庫連接池
- C3P0 資料庫連接池
在使用了資料庫連接池之后,在專案的實際開發中就不需要撰寫連接資料庫的代碼了,直接從資料源獲 得資料庫的連接,
DBCP資料源
DBCP 是 Apache 軟體基金組織下的開源連接池實作,要使用DBCP資料源,需要應用程式應在系統中增 加如下兩個 jar 檔案:
- Commons-dbcp.jar:連接池的實作
- Commons-pool.jar:連接池實作的依賴庫
Tomcat 的連接池正是采用該連接池來實作的,該資料庫連接池既可以與應用服務器整合使用,也可由 應用程式獨立使用,
測驗:
1、匯入相關jar包
2、在類目錄下加入dbcp的組態檔:dbcpconfig.properties
#連接設定 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false username=root password=123456 #<!-- 初始化連接 --> initialSize=10 #最大連接數量 maxActive=50 #<!-- 最大空閑連接 --> maxIdle=20 #<!-- 最小空閑連接 --> minIdle=5 #<!-- 超時等待時間以毫秒為單位 6000毫秒/1000等于60秒 --> maxWait=60000 #JDBC驅動建立連接時附帶的連接屬性屬性的格式必須為這樣:【屬性名=property;】 #注意:"user" 與 "password" 兩個屬性會被明確地傳遞,因此這里不需要包含他們, connectionProperties=useUnicode=true;characterEncoding=UTF8 #指定由連接池所創建的連接的自動提交(auto-commit)狀態, defaultAutoCommit=true #driver default 指定由連接池所創建的連接的只讀(read-only)狀態, #如果沒有設定該值,則“setReadOnly”方法將不被呼叫,(某些驅動并不支持只讀模式,如:Informix) defaultReadOnly= #driver default 指定由連接池所創建的連接的事務級別(TransactionIsolation), #可用值為下列之一:(詳情可見javadoc,)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE defaultTransactionIsolation=READ_UNCOMMITTED
3、撰寫工具類 JdbcUtils_DBCP
package com.fubai.lesson04.utils;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
//資料庫連接工具類
public class JdbcUtils_DBCP {
/**
* 在java中,撰寫資料庫連接池需實作java.sql.DataSource介面,每一種資料庫連接池都
* 是DataSource介面的實作
* DBCP連接池就是java.sql.DataSource介面的一個具體實作
*/
private static DataSource ds = null;
//在靜態代碼塊中創建資料庫連接池
static {
try {
//加載dbcpconfig.properties組態檔
InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties prop = new Properties();
prop.load(in);
//創建資料源
ds = BasicDataSourceFactory.createDataSource(prop);
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
//從資料源中獲取資料庫連接
public static Connection getConnection() throws SQLException {
//從資料源中獲取資料庫連接
return ds.getConnection();
}
// 釋放資源
public static void release(Connection conn, Statement st, ResultSet rs) {
if (rs != null) {
try {
//關閉存盤查詢結果的ResultSet物件
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if (st != null) {
try {
//關閉負責執行SQL命令的Statement物件
st.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
//將Connection連接物件還給資料庫連接池
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
測驗類
package com.fubai.lesson04;
import com.fubai.lesson03.utils.JdbcUtils;
import com.fubai.lesson04.utils.JdbcUtils_DBCP;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestDBCP {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//獲取資料庫連接
connection = JdbcUtils_DBCP.getConnection();
String sql = "select * from users where id = ?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 1);
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
System.out.println("name:" + resultSet.getString("name"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.release(connection, preparedStatement, resultSet);
}
}
}
C3P0
C3P0是一個開源的JDBC連接池,它實作了資料源和JNDI系結,支持JDBC3規范和JDBC2的標準擴展,目 前使用它的開源專案有Hibernate,Spring等,C3P0資料源在專案開發中使用得比較多,
c3p0與dbcp區別
- dbcp沒有自動回收空閑連接的功能
- c3p0有自動回收空閑連接功能
測驗
1、匯入相關jar包
2、在類目錄下加入C3P0的組態檔:c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!--
C3P0的預設(默認)配置,
如果在代碼中“ComboPooledDataSource ds = new ComboPooledDataSource();”這樣寫
就表示使用的是C3P0的預設(默認)配置資訊來創建資料源
-->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcStudy?
useUnicode=true&characterEncoding=utf8&useSSL=false
</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
<!--
C3P0的命名配置,
如果在代碼中“ComboPooledDataSource ds = new
ComboPooledDataSource("MySQL");”這樣寫就表示使用的是name是MySQL的配置資訊來創建資料
源
-->
<named-config name="MySQL">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcStudy?
useUnicode=true&characterEncoding=utf8&useSSL=false
</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</named-config>
</c3p0-config>
3、創建工具類
package com.fubai.lesson04.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcUtils_C3P0 {
private static ComboPooledDataSource ds = null;
//在靜態代碼塊中創建資料庫連接池
static {
try {
//通過代碼創建C3P0資料庫連接池
/*ds = new ComboPooledDataSource();
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbcstudy");
ds.setUser("root");
ds.setPassword("123456");
ds.setInitialPoolSize(10);
ds.setMinPoolSize(5);
ds.setMaxPoolSize(20);*/
//通過讀取C3P0的xml組態檔創建資料源,C3P0的xml組態檔c3p0-config.xml必須放在src目錄下
//ds = new ComboPooledDataSource();//使用C3P0的默認配置來創建資料源
ds = new ComboPooledDataSource("MySQL");//使用C3P0的命名配置來創建資料源
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
//從資料源中獲取資料庫連接
public static Connection getConnection() throws SQLException {
//從資料源中獲取資料庫連接
return ds.getConnection();
}
//釋放資源
public static void release(Connection conn, Statement st, ResultSet rs) {
if (rs != null) {
try {
//關閉存盤查詢結果的ResultSet物件
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if (st != null) {
try {
//關閉負責執行SQL命令的Statement物件
st.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
//將Connection連接物件還給資料庫連接池
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
測驗
package com.fubai.lesson04;
import com.fubai.lesson03.utils.JdbcUtils;
import com.fubai.lesson04.utils.JdbcUtils_C3P0;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestC3P0 {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//獲取資料庫連接
connection = JdbcUtils_C3P0.getConnection();
String sql = "select * from users where id = ?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 1);
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
System.out.println("name:" + resultSet.getString("name"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.release(connection, preparedStatement, resultSet);
}
}
}
本文來自博客園,作者:腹白,轉載請注明原文鏈接:https://www.cnblogs.com/wyh518/
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/527995.html
標籤:其他
上一篇:遞回
