数据库连接池负责分配,管理和释放数据库连接。
优点:
减少连接的创建时间,创建新的JDBC连接仍会招致网络和JDBC驱动的开销。
简化的编程模式
受控的资源使用
连接池能够使性能最大化,还能将资源利用控制在一定的水平之下。
将数据库连接作为对象存储在Vector对象中,一旦数据库连接建立后,不同的数据库访问请求就可以共享这些连接。
数据库连接池的主要操作:
1.建立数据库连接池对象(服务器启动)
2.按照事先指定的参数创建初始数量的数据库连接(即:空闲连接数)
3.对于数据库访问请求,直接从连接池中得到一个连接。数据库连接池对象没有空闲的连接,且连接数没有达到最大,创建一个新的数据库连接。
4.存取数据库
5.关闭数据库,释放所有数据库连接(此时的关闭数据库连接,并非真正关闭,而是将其放入空闲队列中。)
6.释放数据库连接池对象(服务器停止,维护期间,释放数据库连接池对象,并释放所有连接)
连接池使用
servlet的生命周期是:在开始建立servlet时,调用其初始化(init)方法。之后每个用户请求都调用前面建立的实例的service方法的线程。当服务器决定卸载一个servlet时,它首先调用该servlet的destroy方法。根据servlet的特点在初始化函数中生成连接池管理类中的唯一实例(一个或多个连接池)
在service方法中通过连接池名称使用连接池,执行数据库操作。最后在destory方法中释放占用的系统资源。
几个主流的java连接池:
c3p0是一个开放源代码的JDBC连接池。
BoneCP是一个开源快速的JDBC连接池。BoneCP很小,只有四十几K(运行时需要log4j和GoogleCollections的支持,这二者加起来就不小了),相比之下C3P0要六百多K。缺点:JDBC驱动的加载是在连接池之外的,这样在一些应用服务器的配置上就不够灵活。
DBCP是一个依赖Jakarta commons-pool对象池机制的数据库连接池,tomcat的数据源使用的就是DBCP.
Proxool是一个Java SQL Driver驱动程序,提供了对你选择的其它类型的驱动程序的连接池封装。非常简单的移植到现存的代码中。完全可配置。
c3p0连接池使用:c3p0.jar
jdbc.properties
driverClass=org.gjt.mm.mysql.Driver
jdbcUrl=jdbc:mysql://localhost:3306/my_test?useUnicode=true&characterEncoding=utf-8
user=root
password=123456
#<!--初始化时获取的连接数,取值应该minPoolSize与maxPoolSzie之间。-->
initialPoolSize=3
#<!---连接池中保留的最小连接数-->
minPoolSize=1
#<--连接池中保留的最大连接数-->
maxPoolSize=15
#<!--最大空闲时间,600秒内未使用则连接被丢弃。若为0则永不丢弃。Default:0-->
maxIdleTime=200
#<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default:3-->
aquireIncrement=2
#<--每120秒检查所有连接池中的空闲连接。Default:0-->
idleConnectionTestPeriod=120
maxConnectionAge=400
package com.c3p0;
import java.beans.PropertyVetoException;
import java.io.IOException;
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 com.mchange.v2.c3p0.ComboPooledDataSource;
public final class C3p0Source {
private C3p0Source(){
}
private static ComboPooledDataSource dataSource;
static{
try {
dataSource = new ComboPooledDataSource();
Properties properties = new Properties();
InputStream is = C3p0Source.class.getClassLoader().getResourceAsStream("jdbc.properties");//类加载器 返回一个读取指定资源的输入流
properties.load(is);//从输入流中读取属性列表
//dataSource.setProperties(properties);
dataSource.setUser(properties.getProperty("user"));
dataSource.setPassword(properties.getProperty("password"));
dataSource.setJdbcUrl(properties.getProperty("JdbcUrl"));
dataSource.setDriverClass(properties.getProperty("DriverClass"));
dataSource.setInitialPoolSize(Integer.parseInt(properties.getProperty("InitialPoolSize")));
dataSource.setMinPoolSize(Integer.parseInt(properties.getProperty("MinPoolSize")));
dataSource.setMaxPoolSize(Integer.parseInt(properties.getProperty("MaxPoolSize")));
dataSource.setMaxIdleTime(Integer.parseInt(properties.getProperty("MaxIdleTime")));
dataSource.setIdleConnectionTestPeriod(Integer.parseInt(properties.getProperty("IdleConnectionTestPeriod")));
dataSource.setMaxConnectionAge(Integer.parseInt(properties.getProperty("MaxConnectionAge")));
} catch (IOException e) {
e.printStackTrace();
} catch (PropertyVetoException e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public static void realseSource(ResultSet rs,Statement st,Connection conn) throws SQLException{
try{
if(rs!=null){
rs.close();
}
} finally{
try{
if(st != null){
st.close();
}
}finally{
if(conn != null){
conn.close();
}
}
}
}
}
jdbc.properties属性文件可以写成xml格式
早期的c3p0版本对JDBC接口采用动态反射代理。
DBCP连接池使用:commons-dbcp-1.4.jar commons-pool.jar commons-collections-3.2.jar
dbcpconfig.properties
#数据库驱动器全限定名称
driverClassName=org.microsoft.sqlserver.jdbc.SQLServerDriver
#与数据库连接的url
url=jdbc:sqlserver//localhost:1433;DatabaseName=dbTest1
#用户名
username=sa
#密码
password=admin
#连接的初始化个数
initialPoolSize=10
#最大活跃数
maxActive=50
#最大空闲连接数
maxIdle=20
#最小空闲连接数
minIdle=5
#最大等待时间
maxWait=60000
#连接属性
connectionProperties=useUnicode=true;characterEncoding=gbk
#默认是否自动提交
defaultAutoCommit=true
#默认事物隔离级别
defaultTransactionIsolation=Read_COMMITED
package com.c3p0;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
public final class DBCPBean {
//数据源,static
private static DataSource DS;
public Connection getConn(){
try {
return DS.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//默认的构造函数
public DBCPBean(){
}
//构造函数,初始化了DS,指定数据库
public DBCPBean(String connectURI){
initDS(connectURI);
}
public static void initDS(String connectURI){
initDS(connectURI,"root","password","com.mysql.jdbc.Driver",5,100,30,10000);
}
public static void initDS(String connectURI,String username,String pswd,String driverClass,int initialSize,int maxActive,int maxIdle,int maxWait){
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(driverClass);
ds.setUserName(username);
ds.setPassword(pswd);
ds.setUrl(connectURI);
ds.setInitialSize(initialSize);
ds.setMaxWait(maxWait);
DS = ds;
}
//获取数据源连接状态
public static Map<String,Integer> getDataSourceStats() throws SQLException{
BasicDataSource bds = (BasicDataSource)DS;
Map<String,Integer> map = new HashMap<String,Integer>(2);
map.put("active_number", bds.getNumberActive());
map.put("idle_number", bds.getNumberIdle());
return map;
}
//关闭数据源
protected static void shutdownDataSource() throws SQLException{
BasicDataSource bds = (BasicDataSource)DS;
bds.close();
}
}