新聞中心
一種技術(shù)的出現(xiàn),要么是解決實(shí)際問題,要么是優(yōu)化現(xiàn)有技術(shù)。數(shù)據(jù)庫連接池技術(shù)的出現(xiàn),是為了優(yōu)化數(shù)據(jù)庫連接操作的性能。

成都創(chuàng)新互聯(lián)公司2013年至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都做網(wǎng)站、成都網(wǎng)站制作網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢想脫穎而出為使命,1280元洪山做網(wǎng)站,已為上家服務(wù),為洪山各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:028-86922220
在使用JDBC進(jìn)行數(shù)據(jù)庫開發(fā)的時(shí)候,一般經(jīng)歷這樣一個(gè)過程:
1)加載數(shù)據(jù)庫的驅(qū)動(dòng)
2)建立數(shù)據(jù)庫的連接(Connection)
3)創(chuàng)建SQL語句聲明(Statement)
4)執(zhí)行更新(executeUpdate)或查詢(executeQuery)
本文中講的數(shù)據(jù)庫連接池,只是針對Connection的部分的優(yōu)化。
學(xué)習(xí)連接池
a. 自定義一個(gè)連接池
b. 學(xué)習(xí)優(yōu)秀的連接池組件
1)DBCP
2)C3P0
1、引入
思考:程序中Connection連接是如何管理的?
數(shù)據(jù)庫的連接(Connection)涉及到的操作有:a)數(shù)據(jù)庫操作開始,創(chuàng)建連接,b)操作結(jié)束,關(guān)閉連接。
我們知道連接資源十分寶貴,因此需要對它進(jìn)行管理。如果頻繁的打開和關(guān)閉連接,會(huì)影響程序的運(yùn)行效率!
連接管理的思路:預(yù)先創(chuàng)建一組連接,用的時(shí)候每次取出一個(gè);用完之后,將連接放回去。
2、自定義連接池
第一個(gè)版本
package com.rk.pool;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
/**
* 自定義連接池,管理連接(Connection)
* 全局參數(shù):初始化數(shù)目、最大連接數(shù)、當(dāng)前連接數(shù)、連接池集合
*
* 當(dāng)啟動(dòng)的時(shí)候,就有3(init_count)個(gè)初始連接Connection
* 1.創(chuàng)建連接的方法createConnection()
* 2.提供獲取連接的方法getConnection()
* 2.1如果有空閑連接,則直接返回
* 2.2如果沒有空閑連接,且沒有達(dá)到最大限制數(shù)量,則創(chuàng)建連接返回
* 2.3如果沒有空閑連接,且連接數(shù)據(jù)達(dá)到最大限制數(shù),則無法獲取到連接,返回null
* 3.提供釋放連接的方法releaseConnection(Connection conn)
* 3.1如果連接池內(nèi)的空閑連接數(shù)量小于初始的連接數(shù)量,則當(dāng)前連接返回到連接池中
* 3.2如果連接池內(nèi)的空閑連接數(shù)量等于初始的連接數(shù)量,則將當(dāng)前連接關(guān)閉
* @author lsieun
*
*/
public class MyConnectionPool
{
private final static String url = "jdbc:MySQL:///testdb";
private final static String driverClassName = "com.mysql.jdbc.Driver";
private final static String user = "root";
private final static String password = "root";
private LinkedList freeConnections = null;//// 連接池 (存放所有的初始化連接)
private final int init_count = 3;//初始的連接(Connection)數(shù)量(最小值)
private final int max_count = 6;//最大的連接數(shù)量(最大值)
private int current_count = 0;//當(dāng)前擁有的連接數(shù)量(當(dāng)前值)
/**
* 靜態(tài)代碼塊,加載數(shù)據(jù)庫的驅(qū)動(dòng)程序
*/
static
{
try
{
Class.forName(driverClassName);
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}
}
//1.初始化
public MyConnectionPool() throws SQLException
{
//初始化連接池
freeConnections = new LinkedList();
//將指定數(shù)量(init_cont)加入到連接池中
for(int i=0;i0)
{
return freeConnections.removeFirst();
}
else if(current_count" + pool.getCurrentCount());
Connection conn1 = pool.getConnection();
Connection conn2 = pool.getConnection();
Connection conn3 = pool.getConnection();
System.out.println("3-->" + pool.getCurrentCount());
Connection conn4 = pool.getConnection();
System.out.println("4-->" + pool.getCurrentCount());
Connection conn5 = pool.getConnection();
System.out.println("5-->" + pool.getCurrentCount());
Connection conn6 = pool.getConnection();
System.out.println("6-->" + pool.getCurrentCount());
Connection conn7 = pool.getConnection();
System.out.println("7-->" + pool.getCurrentCount());
*/
MyConnectionPool pool = new MyConnectionPool();
System.out.println("0-->" + pool.getCurrentCount());
Connection conn1 = pool.getConnection();
Connection conn2 = pool.getConnection();
Connection conn3 = pool.getConnection();
System.out.println("3-->" + pool.getCurrentCount());
pool.releaseConnection(conn1);
Connection conn4 = pool.getConnection();
System.out.println("4-->" + pool.getCurrentCount());
}
} 第二個(gè)版本(在創(chuàng)建Connection時(shí),增加了動(dòng)態(tài)代理)
如果開發(fā)人員得到Connection對象時(shí),并調(diào)用它的close方法,并不會(huì)關(guān)閉連接,而是將Connection對象放回到連接池中,這就是通過動(dòng)態(tài)代理來實(shí)現(xiàn)的。
如果對某個(gè)接口中的某個(gè)指定的方法的功能進(jìn)行擴(kuò)展,而不想實(shí)現(xiàn)接口里所有方法,可以使用(動(dòng)態(tài))代理模式! 使用動(dòng)態(tài)代理,可以監(jiān)測接口中方法的執(zhí)行!
Java中代理模式:靜態(tài)/動(dòng)態(tài)/Cglib代理(spring)
如何對Connection對象,生成一個(gè)代理對象:
|--Proxy
static Object newProxyInstance(
ClassLoader loader, 當(dāng)前使用的類加載器
Class>[] interfaces, 目標(biāo)對象(Connection)實(shí)現(xiàn)的接口類型
InvocationHandler h 事件處理器:當(dāng)執(zhí)行上面接口中的方法的時(shí)候,就會(huì)自動(dòng)觸發(fā)事件處理器代碼,把當(dāng)前執(zhí)行的方法(method)作為參數(shù)傳入。
)
package com.rk.pool;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
/**
* 自定義連接池,管理連接(Connection)
* 全局參數(shù):初始化數(shù)目、最大連接數(shù)、當(dāng)前連接數(shù)、連接池集合
*
* 當(dāng)啟動(dòng)的時(shí)候,就有3(init_count)個(gè)初始連接Connection
* 1.創(chuàng)建連接的方法createConnection()
* 2.提供獲取連接的方法getConnection()
* 2.1如果有空閑連接,則直接返回
* 2.2如果沒有空閑連接,且沒有達(dá)到最大限制數(shù)量,則創(chuàng)建連接返回
* 2.3如果沒有空閑連接,且連接數(shù)據(jù)達(dá)到最大限制數(shù),則無法獲取到連接,返回null
* 3.提供釋放連接的方法releaseConnection(Connection conn)
* 3.1如果連接池內(nèi)的空閑連接數(shù)量小于初始的連接數(shù)量,則當(dāng)前連接返回到連接池中
* 3.2如果連接池內(nèi)的空閑連接數(shù)量等于初始的連接數(shù)量,則將當(dāng)前連接關(guān)閉
* @author lsieun
*
*/
public class MyConnectionPoolUpdate
{
private final static String url = "jdbc:mysql:///testdb";
private final static String driverClassName = "com.mysql.jdbc.Driver";
private final static String user = "root";
private final static String password = "root";
private LinkedList freeConnections = null;//// 連接池 (存放所有的初始化連接)
private final int init_count = 3;//初始的連接(Connection)數(shù)量(最小值)
private final int max_count = 6;//最大的連接數(shù)量(最大值)
private int current_count = 0;//當(dāng)前擁有的連接數(shù)量(當(dāng)前值)
/**
* 靜態(tài)代碼塊,加載數(shù)據(jù)庫的驅(qū)動(dòng)程序
*/
static
{
try
{
Class.forName(driverClassName);
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}
}
//1.初始化
public MyConnectionPoolUpdate() throws SQLException
{
//初始化連接池
freeConnections = new LinkedList();
//將指定數(shù)量(init_cont)加入到連接池中
for(int i=0;i0)
{
return freeConnections.removeFirst();
}
else if(current_count" + pool.getCurrentCount());
Connection conn1 = pool.getConnection();
conn1.close();
}
} 3、開源的連接池技術(shù)
Sun公司約定: 如果是連接池技術(shù),需要實(shí)現(xiàn)一個(gè)接口:javax.sql.DataSource!
注意,DataSource位于javax.sql包下,而不是java.sql包下,其中x表示擴(kuò)展的意思。
下面是DataSource的源代碼,它只提供了兩個(gè)重載方法getConnection。
public interface DataSource extends CommonDataSource,Wrapper {
/**
* Attempts to establish a connection with the data source that
* this DataSource object represents.
*/
Connection getConnection() throws SQLException;
/**
*
Attempts to establish a connection with the data source that
* this DataSource object represents.
*/
Connection getConnection(String username, String password)
throws SQLException;
}
javax.sql.DataSource接口
(1)DataSource object是對DriverManager的一種替代。推薦使用DataSource來獲得Connection對象。
An alternative to the DriverManager facility, a DataSource object is the preferred means of getting a connection.
(2)實(shí)現(xiàn)DataSource接口的object常常是用JNDI注冊的。
An object that implements the DataSource interface will typically be registered with a naming service based on the JavaTM Naming and Directory (JNDI) API.
(3)DataSource接口由driver vendor實(shí)現(xiàn),有三種實(shí)現(xiàn)類型:
3.1)Basic implementation:基本實(shí)現(xiàn),產(chǎn)生標(biāo)準(zhǔn)的Connection對象
3.2)Connection pooling implementation:連接池實(shí)現(xiàn),有connection pool,由a middle-tier connection pooling manager
3.3)Distributed transaction implementation:分布式事務(wù)實(shí)現(xiàn),由a middle-tier transaction manager和a connection pooling manager.
The DataSource interface is implemented by a driver vendor. There are three types of implementations:
a)Basic implementation -- produces a standard Connection object
b)Connection pooling implementation -- produces a Connection object that will automatically participate in connection pooling. This implementation works with a middle-tier connection pooling manager.
c)Distributed transaction implementation -- produces a Connection object that may be used for distributed transactions and almost always participates in connection pooling. This implementation works with a middle-tier transaction manager and almost always with a connection pooling manager.
(4)通過DataSource獲得的driver,并不會(huì)用DriverManager注冊。
回憶一下:DriverManager可以注冊驅(qū)動(dòng)。
Driver driver = new com.mysql.jdbc.Driver();
//注冊驅(qū)動(dòng)程序(可以注冊多個(gè)驅(qū)動(dòng)程序)
DriverManager.registerDriver(driver);
A driver that is accessed via a DataSource object does not register itself with the DriverManager. Rather, a DataSource object is retrieved though a lookup operation and then used to create a Connection object.
(5)如果是basic implementation,那么通過DataSource object獲得的Connection與通過DriverManager獲得的Connection是一樣的。
With a basic implementation, the connection obtained through a DataSource object is identical to a connection obtained through the DriverManager facility.
3.1、DBCP連接池
DBCP 是 Apache 軟件基金組織下的開源連接池實(shí)現(xiàn),使用DBCP數(shù)據(jù)源,應(yīng)用程序應(yīng)在系統(tǒng)中增加如下兩個(gè) jar 文件:
Commons-dbcp.jar:連接池的實(shí)現(xiàn)
Commons-pool.jar:連接池實(shí)現(xiàn)的依賴庫
Tomcat 的連接池正是采用該連接池來實(shí)現(xiàn)的。該數(shù)據(jù)庫連接池既可以與應(yīng)用服務(wù)器整合使用,也可由應(yīng)用程序獨(dú)立使用。
核心類:BasicDataSource
使用步驟
引入jar文件
commons-dbcp-1.4.jar
http://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi
commons-pool-1.6.jar
http://commons.apache.org/proper/commons-pool/download_pool.cgi
使用連接池,創(chuàng)建連接
a) 硬編碼方式
b) 配置方式(db.properties)
package com.rk.dbcp;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.junit.Test;
public class Demo
{
// 1. 硬編碼方式實(shí)現(xiàn)連接池
@Test
public void testDbcp() throws SQLException
{
// DBCP連接池核心類
BasicDataSource dataSource = new BasicDataSource();
// 連接池參數(shù)配置: 連接字符串、驅(qū)動(dòng)、用戶、密碼
dataSource.setUrl("jdbc:mysql:///testdb");//"jdbc:mysql://localhost:3306/testdb"
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("root");
// 連接池參數(shù)配置:初始化連接數(shù)、最大連接數(shù) 、最大空閑時(shí)間
dataSource.setInitialSize(3);
dataSource.setMaxActive(6);
dataSource.setMaxIdle(3000);
// 獲取連接
Connection conn = dataSource.getConnection();
System.out.println(conn);
conn.prepareStatement("DELETE FROM T_Student WHERE Id=10").executeUpdate();
// 關(guān)閉
conn.close();
}
@Test
// 2. 【推薦】配置方式實(shí)現(xiàn)連接池 , 便于維護(hù)
public void testProp() throws Exception
{
// 獲取文件流
InputStream inStream = Demo.class.getResourceAsStream("db.properties");
//創(chuàng)建Properties對象
Properties prop = new Properties();
// 加載屬性配置文件
prop.load(inStream);
// 根據(jù)prop配置,直接創(chuàng)建數(shù)據(jù)源對象
DataSource dataSource = BasicDataSourceFactory.createDataSource(prop);
// 獲取連接
Connection conn = dataSource.getConnection();
System.out.println(conn);
conn.prepareStatement("DELETE FROM T_Student WHERE Id=10").executeUpdate();
// 關(guān)閉
conn.close();
}
}配置方式實(shí)現(xiàn)DBCP連接池, 配置文件中的key與BaseDataSouce中的屬性一樣:
url=jdbc:mysql://localhost:3306/testdb driverClassName=com.mysql.jdbc.Driver username=root password=root initialSize=3 maxActive=6 maxIdle=3000
org.apache.commons.dbcp.BasicDataSource
(1)Apache的DBCP中的核心類BasicDataSource是對javax.sql.DataSource接口的Basic implementation。
Basic implementation of javax.sql.DataSource that is configured via JavaBeans properties.
org.apache.commons.dbcp.BasicDataSourceFactory
(1)BasicDataSourceFactory是一個(gè)JNDI object factory,用于創(chuàng)建一個(gè)BasicDataSource實(shí)例。
JNDI object factory that creates an instance of BasicDataSource.
3.2、C3P0連接池
C3P0連接池:最常用的連接池技術(shù)!Spring框架,默認(rèn)支持C3P0連接池技術(shù)!
核心類:ComboPooledDataSource
使用:
1.下載,引入jar文件: c3p0-0.9.1.2.jar
https://sourceforge.net/projects/c3p0/
http://www.mchange.com/projects/c3p0/
2. 使用連接池,創(chuàng)建連接
a) 硬編碼方式
b) 配置方式(xml)
package com.rk.c3p0;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;
import org.junit.Test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class Demo
{
@Test
//1. 硬編碼方式,使用C3P0連接池管理連接
public void testCode() throws PropertyVetoException, SQLException
{
// 創(chuàng)建連接池核心工具類
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 設(shè)置連接參數(shù):url、驅(qū)動(dòng)、用戶密碼、初始連接數(shù)、最大連接數(shù)
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/testdb");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setUser("root");
dataSource.setPassword("root");
dataSource.setInitialPoolSize(3);
dataSource.setMaxPoolSize(6);
dataSource.setMaxIdleTime(1000);
// ---> 從連接池對象中,獲取連接對象
Connection conn = dataSource.getConnection();
System.out.println(conn);
conn.prepareStatement("DELETE FROM T_Student WHERE Id=10").executeUpdate();
// 關(guān)閉
conn.close();
}
@Test
//2. XML配置方式,使用C3P0連接池管理連接
public void testXML() throws SQLException
{
// 創(chuàng)建c3p0連接池核心工具類
// 自動(dòng)加載src下c3p0的配置文件【c3p0-config.xml】
ComboPooledDataSource dataSource = new ComboPooledDataSource();// 使用默認(rèn)的配置
//ComboPooledDataSource dataSource = new ComboPooledDataSource("oracle_config");// 使用指定的配置
// ---> 從連接池對象中,獲取連接對象
Connection conn = dataSource.getConnection();
System.out.println(conn);
conn.prepareStatement("DELETE FROM T_Student WHERE Id=10").executeUpdate();
// 關(guān)閉
conn.close();
}
}c3p0-config.xml文件放在src目錄下
jdbc:mysql://localhost:3306/testdb com.mysql.jdbc.Driver root root 3 6 1000 jdbc:mysql://localhost:3306/testdb com.mysql.jdbc.Driver root root 3 6 1000
當(dāng)前標(biāo)題:開源組件:(1)DBCP和C3P0
URL鏈接:http://www.dlmjj.cn/article/gcdccp.html


咨詢
建站咨詢
