JDBC數據庫連接池
數據庫連接池(connection pool)的工作原理
1、基本概念及原理
由上面的分析可以看出,問題的根源就在于對數據庫連接資源的低效管理。我們知道,
對于共享資源,有一個很著名的設計模式:資源池(Resource Pool)。該模式正是為了解決資源的頻繁分配﹑釋放所造成的問題。為解決上述問題,可以采用數據庫連接池技術。數據庫連接池的基本思想就是為數據庫連接建立一個“緩沖池”。預先在緩沖池中放入一定數量的連接,當需要建立數據庫連接時,只需從“緩沖池”中取出一個,使用完畢之后再放回去。我們可以通過設定連接池最大連接數來防止系統無盡的與數據庫連接。更為重要的是我們可以通過連接池的管理機制監視數據庫的連接的數量﹑使用情況,為系統開發﹑測試及性能調整提供依據。
連接池的基本工作原理
2、服務器自帶的連接池
JDBC的API中沒有提供連接池的方法。一些大型的WEB應用服務器如BEA的WebLogic和IBM的WebSphere等提供了連接池的機制,但是必須有其第三方的專用類方法支持連接池的用法。
編寫數據庫連接池:
首先編寫數據庫連接池需要實現java,sql.DataSource接口,DataSource接口中定義了兩個重載的getConnection()方法,實現DataSource接口后,在構造函數中批量創建與數據庫的連接,并把創建的連接加入到linkedList對象中,實現getConnection方法,讓這個方法每次調用的時候從linkedList中取出來一個連接給用戶,當用戶使用完畢connection調用close方法時,Collection對象要保證將自己返回到鏈表中而不要把連接返還給數據庫。首先我們來看如何獲取數據庫的連接并且存放在鏈表中
先我們來看如何獲取數據庫的連接并且存放在鏈表中:
package com.csdn.tool;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
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;
import java.util.Properties;
import javax.sql.DataSource;
public class MyJdbcDemo implements DataSource{
private static LinkedList<Connection> list = new LinkedList<Connection>();
private static String driver;
private static String url;
private static String username;
private static String password;
static{
InputStream in = MyJdbcDemo.class.getClassLoader().getResourceAsStream("db.properties");
Properties prop= new Properties();
try {
prop.load(in);
driver=prop.getProperty("driver");
url=prop.getProperty("url");
username=prop.getProperty("username");
password = prop.getProperty("password");
//注冊驅動
Class.forName(driver);
//通過DriverManager獲取一批Connection集合;
for(int i=0;i<10;i++){
Connection conn=DriverManager.getConnection(url,username,password);
System.out.println("向池中加入了"+conn);
list.add(conn);//加入集合;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public Connection getConnection() throws SQLException {
if(list.size()>0){
final Connection conn=list.removeFirst();//mysql的一個實現
System.out.println("用戶從池中取走了:"+conn);
System.out.println("池的大小為: "+list.size());
return (Connection) Proxy.newProxyInstance(MyJdbcDemo.class.getClassLoader(),new Class[]{Connection.class},new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(!method.getName().equalsIgnoreCase("close")){
return method.invoke(conn, args);
}
System.out.println(conn+"被還了");
list.add(conn);
System.out.println("池的大小為"+list.size());
return null;
}
});
}else{
throw new RuntimeException("請稍等");
}
}
還有dbcp方法:
DBCP是Apache軟件基金組織下的開源連接池實現,使用DBCP數據源,應用程序應在系統中增加如下兩個jar文件:Commons-dbcp.jar Commons-pool.jar
Tomcat的連接池正是采用該連接池來實現的。該數據庫連接池既可以與應用服務器整合使用,也可由應用程序獨立使用
先寫好配置文件,解決亂碼問題,在工具中都改為gbk就行了#連接設置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/javaweb
username=root
password=root
#<!-- 初始化連接 -->
initialSize=10
#最大連接數量
maxActive=50
#<!-- 最大空閑連接 -->
maxIdle=20
#<!-- 最小空閑連接 -->
minIdle=5
#<!-- 超時等待時間以毫秒為單位 6000毫秒/1000等于60秒 -->
maxWait=60000
#JDBC驅動建立連接時附帶的連接屬性屬性的格式必須為這樣:[屬性名=property;]
#注意:"user" 與 "password" 兩個屬性會被明確地傳遞,因此這里不需要包含他們。
connectionProperties=useUnicode=true;characterEncoding=gbk
#指定由連接池所創建的連接的自動提交(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
//編寫類
public class DBManager_dbcp {
private static DataSource ds;
static{
try{
InputStream in = DBManager.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties prop = new Properties();
prop.load(in);
BasicDataSourceFactory factory = new BasicDataSourceFactory();
ds=factory.createDataSource(prop);
}catch(Exception e){
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
}
C3p0配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/javaweb</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
<named-config name="mysql">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/javaweb</property>
<property name="user">root</property>
<property name="password">root</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>
文件類:
package com.csdn.tool;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3p0Demo1 {
private static ComboPooledDataSource ds=null;
static{
ds = new ComboPooledDataSource();
try {
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/javaweb");
ds.setUser("root");
ds.setPassword("root");
ds.setInitialPoolSize(10);
ds.setMaxPoolSize(40);
ds.setMinPoolSize(5);
} catch (PropertyVetoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
}