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重连设置:
设置获取连接失败后,是否重新连接以及间隔时间。