DBCP、c3p0、Druid三大连接池区别
一、连接池优势
如果一个项目中如果需要多个连接,如果一直获取连接,断开连接,这样比较浪费资源;
如果创建一个池,用池来管理Connection,这样就可以重复使用Connection。
有了池我们就不用自己来创建Connection,而是通过池来获取Connection对象。当使用完Connection后,调用Connection的close()方法也不会真的关闭Connection,而是把Connection“归还”给池。
池就可以再利用这个Connection对象了。这里我们常用的连接池有三种,分别是:DBCP连接池、C3P0连接池和DRUID连接池;
二、DBCP连接池
DBCP是一个依赖Jakarta commons-pool对象池机制的数据库连接池.DBCP可以直接的在应用程序中使用,Tomcat的数据源使用的就是DBCP;
使用连接池的第一项工作就是导包,这里需要的两个jar包分别是:
在使用写连接池工具类的时候,可以通过配置文件来连接数据库,配置文件中记录了连接数据库的驱动、URL、用户名和密码等信息;但要注意这里的文件后缀为:“.properties”。
把通过配置文件连接数据库的部分写在静态代码块中,随着类的加载只加载一次。出了连接数据库,还要提供一个获得数据源的方法和一个获取连接的方法;
下边是把连接池写成一个工具类的代码,写成工具类和直接使用的代码几乎相同,就不在重复的写了。
配置文件的部分内容:
代码:(配置文件的命名为:dbcp.properties)
public class DBCPUtils {
//首先定义私有的datasource
private static DataSource datasource;
//把配置文件部分放在静态代码块中,调用时直接加载
static{
try {
//加载文件
InputStream is=DBCPUtils.class.getClassLoader().getResourceAsStream("dbcp.properties");
//实例化properties集合
Properties prop=new Properties();
prop.load(is);
//首先加载核心类
datasource=BasicDataSourceFactory.createDataSource(prop);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//提供获得数据源
public static DataSource getDataSource(){
return datasource;
}
//提供获得连接
public static Connection getConnection() throws SQLException{
return datasource.getConnection();
}
}
在写成工具类后都要对外提供一个数据源DateSource和一个连接Connection。作用是,如果我们在进行数据库操作的时候要是使用DBUtils类的时候,就要使用QueryRunner核心类,而这个类在进行与数据库连接的时候只要一句代码:QueryRunner qr=newQueryRunner(数据源);
通过连接池获得:DBCPUtils.getDataSource()获得。如果不使用DBUtils工具类,我们就可以直接通过DBCPUtils .getConnection()来直接获得连接。
三、C3P0连接池
c3p0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。
使用连接池的第一项工作就是导包,这里需要的两个jar包分别是:
这种连接池在进行数据库的连接的时候有两种连接方法:使用配置文件和不使用配置文件两种。
当然使用配置文件的时候代码要简介的多,配置文件中同样是记录了连接数据库的驱动、URL、用户名和密码等信息。
(1)不使用配置文件的代码:三个步骤:
<1>、导入核心类:ComboPooledDataSource
<2>、基本的四项设置,也就是设置驱动,URL,用户名和密码等四项。
<3>、其他四项。代码如下:
public class c3p0_test01 {
public static void main(String[] args) throws Exception {
//导入一个核心类
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//基本四项设置
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/eeday09");
dataSource.setUser("root");
dataSource.setPassword("123");
//其他四项设置
dataSource.setInitialPoolSize(10); //初始化连接个数
dataSource.setMaxPoolSize(40); //最大链接数
dataSource.setMinPoolSize(5); //设置最小链接数
dataSource.setAcquireIncrement(2); //设置每次增加的连接数
Connection conn=dataSource.getConnection(); //进行数据库连接
System.out.println(conn);
}
}
(2)如果使用配置文件连接数据库,其中配置文件中的内容为:
使用配置文件进行连接的写法如下:
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbutils.QueryRunner;
import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0Utils {
//1、提供私有化的数据源 使用默认设置
private static ComboPooledDataSource datasource=new ComboPooledDataSource();
//使用命名配置
//private static ComboPooledDataSource datasource =new ComboPooledDataSource("itheima");
//2.提供对外的数据源
public static DataSource getDataSource(){
return datasource;
}
//3.提供对外的链接
public static Connection getConnection() throws SQLException{
return datasource.getConnection();
}
}
在写成工具类后都要对外提供一个数据源DateSource和一个连接Connection。作用是,如果我们在进行数据库操作的时候要是使用DBUtils类的时候,就要使用QueryRunner核心类,而这个类在进行与数据库连接的时候只要一句代码:QueryRunner qr=newQueryRunner(数据源);
我们可以通过连接池获得:C3P0Utils.getDataSource() 获得。如果不使用DBUtils工具类,我们就可以直接通过C3P0Utils.getConnection()来直接获得连接。
四、Druid连接池
Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。
它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个 SQL Parser。支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等等。Druid针对Oracle和MySql做了特别优化,比如Oracle的PS Cache内存占用优化,MySql的ping检测优化。Druid提供了MySql、Oracle、Postgresql、SQL-92的SQL的完整支持,这是一个手写的高性能SQL Parser,支持Visitor模式,使得分析SQL的抽象语法树很方便。简单SQL语句用时10微秒以内,复杂SQL用时30微秒。通过Druid提供的SQL Parser可以在JDBC层拦截SQL做相应处理,比如说分库分表、审计等。Druid防御SQL注入攻击的WallFilter就是通过Druid的SQL Parser分析语义实现的。
使用步骤:
1,使用连接池的第一项工作就是导包,这里需要的jar包分别是:druid-1.1.4.jar 1.1.4
2,druid.properties 文件内容:
# 配置数据库的连接参数
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test
username=root
password=root
# 配置连接池的参数
initialSize=5
maxActive=10
maxWait=3000
maxIdle=6
minIdle=3
3,连接池工具类:
/**
1)创建私有静态数据源成员变量DataSource ds
2)在静态代码块中创建连接池
a)创建属性对象
b)从类路径下加载属性文件,得到输入流对象
c)通过工厂类创建一个数据源
3)创建公有的得到数据源的方法getDataSource()
4)创建得到连接对象的方法 getConnection()
5)创建释放资源的方法 close()
*/ /**
* 连接池的工具类
*/
public class DataSourceUtils {
//创建一个成员变量
private static DataSource ds;
/**
* 加载的代码写在静态代码块中
*/
static {
try {
Properties info = new Properties();
//加载类路径下,即src目录下的druid.properties这个文件
info.load(DataSourceUtils.class.getResourceAsStream("/druid.properties")); //读取属性文件创建连接池
ds = DruidDataSourceFactory.createDataSource(info);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 得到数据源
*/
public static DataSource getDataSource() {
return ds;
}
/**
* 得到连接对象
*/
public static Connection getConnection() {
try {
return ds.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 释放资源
*/
public static void close(Connection conn, Statement stmt, ResultSet rs) {
if (rs!=null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt!=null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn!=null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(Connection conn, Statement stmt) {
close(conn, stmt, null);
}
}
4,数据源工具类的使用:
public class DemoAdd {
public static void main(String[] args) {
//1. 创建连接对象,通过连接池工具类
Connection conn = null;
PreparedStatement ps = null;
int row = 0;
try {
conn = DataSourceUtils.getConnection();
//2. 创建语句对象
ps = conn.prepareStatement("INSERT INTO student values(null,?,?,?)");
ps.setString(1,"张辽");
ps.setInt(2,1);
ps.setString(3,"194-06-16");
//3. 使用executeUpdate()写入到数据库
row = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//4. 释放资源
DataSourceUtils.close(conn, ps);
}
System.out.println("添加了" + row);
}
}
五、三者区别
我们从连接池配置的基本配置、关键配置、性能配置等主要配置来分析:
1,基本配置
注:在Druid连接池的配置中,driverClassName可配可不配,如果不配置会根据url自动识别dbType(数据库类型),然后选择相应的driverClassName。
2,关键配置
注1:在DBCP连接池的配置中,还有一个maxIdle的属性,表示最大空闲连接数,超过的空闲连接将被释放,默认值为8。对应的该属性在Druid连接池已不再使用,配置了也没有效果,c3p0连接池则没有对应的属性。
3,性能配置
(1)预缓存设置:
(2)连接有效性检测设置:
连接池内部有机制判断,如果当前的总的连接数少于miniIdle,则会建立新的空闲连接,以保证连接数得到miniIdle。如果当前连接池中某 个连接在空闲了timeBetweenEvictionRunsMillis时间后任然没有使用,则被物理性的关闭掉。有些数据库连接的时候有超时限制 (mysql连接在8小时后断开),或者由于网络中断等原因,连接池的连接会出现失效的情况,这时候设置一个testWhileIdle参数为true, 可以保证连接池内部定时检测连接的可用性,不可用的连接会被抛弃或者重建,最大情况的保证从连接池中得到的Connection对象是可用的。当然,为了 保证绝对的可用性,你也可以使用testOnBorrow为true(即在获取Connection对象时检测其可用性),不过这样会影响性能。
(3)超时连接关闭设置:
removeAbandoned参数,用来检测到当前使用的连接是否发生了连接泄露,所以在代码内部就假定如果一个连接建立连接的时间很长,则将其认定为泄露,继而强制将其关闭掉。
(4)c3p0重连设置:
设置获取连接失败后,是否重新连接以及间隔时间。