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(); } }