0、DBCP简介

     DBCP(DataBase connection pool)数据库连接池是 apache 上的一个Java连接池项目。DBCP通过连接池预先同数据库建立一些连接放在内存中(即连接池中),应用程序需要建立数据库连接时直接到从接池中申请一个连接使用,用完后由连接池回收该连接,从而达到连接复用,减少资源消耗的目的。

1、DBCP所依赖的jar包(以下例子基于如下jar包版本)

   commons-dbcp2-2.1.1.jar       commons-logging-1.2.jar       commons-pool2-2.4.2.jar

2、DBCP使用示例

  下图是在Eclipse中创建的Java工程,使用了DBCP相关的jar包,mysql的jdbc驱动jar包,junit4 。

   并在src同级目录下创建了config目录,用于存放DBCP的配置文件。

【注】类DBCPUtil.java在下面的例子中未用到。

  

  1) DBCP配置文件dbcp.properties

########DBCP配置文件##########
#驱动名driverClassName=com.mysql.jdbc.Driver#urlurl=jdbc:mysql://127.0.0.1:3306/mydb#用户名username=sa#密码password=123456#初试连接数initialSize=30#最大活跃数maxTotal=30#最大idle数maxIdle=10#最小idle数minIdle=5#最长等待时间(毫秒)maxWaitMillis=1000#程序中的连接不使用后是否被连接池回收(该版本要使用removeAbandonedOnMaintenance和removeAbandonedOnBorrow)#removeAbandoned=trueremoveAbandonedOnMaintenance=trueremoveAbandonedOnBorrow=true#连接在所指定的秒数内未使用才会被删除(秒)(为配合测试程序才配置为1秒)removeAbandonedTimeout=1

  

  2) 创建初始化DBCP的类KCYDBCPUtil.java  

  package dbcp;

  import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp2.BasicDataSourceFactory; /**
* DBCP配置类
* @author SUN
*/
public class KCYDBCPUtil { private static Properties properties = new Properties();
private static DataSource dataSource;
//加载DBCP配置文件
static{
try{
FileInputStream is = new FileInputStream("config/dbcp.properties");
properties.load(is);
}catch(IOException e){
e.printStackTrace();
} try{
dataSource = BasicDataSourceFactory.createDataSource(properties);
}catch(Exception e){
e.printStackTrace();
}
} //从连接池中获取一个连接
public static Connection getConnection(){
Connection connection = null;
try{
connection = dataSource.getConnection();
}catch(SQLException e){
e.printStackTrace();
}
try {
connection.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
} public static void main(String[] args) {
getConnection();
}
}

  3) 创建使用JDBC获取数据库连接的类DBConn.java(用于和DBCP连接池对比)

  import java.sql.Connection;
import java.sql.DriverManager; public class DBConn {
private static Connection conn = null; //获取一个数据库连接
public static Connection getConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
String dbUrl = "jdbc:mysql://127.0.0.1:3306/mydb";
conn = DriverManager.getConnection(dbUrl, "sa", "123456");
// System.out.println("========数据库连接成功========");
} catch (Exception e) {
e.printStackTrace();
// System.out.println("========数据库连接失败========");
return null;
}
return conn;
}
}

  4) 创建测试类DBCPTest.java

    测试类中采用3中方法将2000个数据插入数据库同一张表中,每次插入数据之前,先清空表,并对结果进行了对比。

    3中插入数据方法如下:

    (1) 每次插入一条数据前,就创建一个连接,该条数据插入完成后,关闭该连接;

   (2) 使用DBCP连接池,每次插入一条数据前,从DBCP连接池中获取一条连接,该条数据插入完成后,该连接交由DBCP连接池管理;

    (3) 在插入数据之前创建一条连接,2000个数据全部使用该连接,2000个数据插入完毕后,关闭该连接。

  package dbcp;

  import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement; import org.junit.Test; public class DBCPTest { //测试,每写一条数据前,就新建一个连接
@Test
public void testWriteDBByEveryConn() throws Exception{
for(int i = 0; i < 2000; i++){
writeDBByEveryConn(i);
}
System.out.println("DONE"); } //测试,使用连接池,每写一条数据前,从连接池中获取一个连接
@Test
public void testWriteDBByDBCP() throws Exception{
for(int i = 0; i < 2000; i++){
writeDBByDBCP(i);
}
System.out.println("DONE");
} //测试,只建一条连接,写入所有数据
@Test
public void testWriteDBByOneConn() throws Exception{
Connection conn = DBConn.getConnection();
Statement stat = conn.createStatement();
for(int i = 0; i < 2000; i++){
writeDBByOneConn(i, stat);
}
conn.close();
System.out.println("DONE");
} //不使用连接池写数据库,每写一条数据创建一个连接
public void writeDBByEveryConn(int data){
String sql = "insert into dbcp values (" + data + ")";
Connection conn = DBConn.getConnection();
try{
Statement stat = conn.createStatement();
stat.executeUpdate(sql);
}catch(Exception e){
e.printStackTrace() ;
}finally{
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
} }
} //不使用连接池写数据库,只用一个连接,写所有数据
public void writeDBByOneConn(int data, Statement stat){
String sql = "insert into dbcp values (" + data + ")";
try{
stat.executeUpdate(sql);
}catch(Exception e){
e.printStackTrace() ;
}
} //通过DBCP连接池写数据库
public void writeDBByDBCP(int data){
String sql = "insert into dbcp values (" + data + ")";
try {
Connection conn = KCYDBCPUtil.getConnection();
Statement stat = conn.createStatement();
stat.executeUpdate(sql);
conn.commit();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
} } 

  测试结果如下:

  (1) 每次插入一条数据前,就创建一个连接,该条数据插入完成后,关闭该连接。耗时158.318秒

   

  (2) 使用DBCP连接池,每次插入一条数据前,从DBCP连接池中获取一条连接,该条数据插入完成后,该连接交由DBCP连接池管理。耗时122.404秒

   

  (3) 在插入数据之前创建一条连接,2000个数据全部使用该连接,2000个数据插入完毕后,关闭该连接。耗时117.87秒

   

  通过对比结果看出,向同一个表中插入2000条数据,每插入一条数据前创建一个新连接,会非常耗时,而使用DBCP连接池和使用同一个连接操作,耗时比较接近。

3、相关问题

  1) 应用程序中,使用完一个数据库连接后,DBCP连接池如何管理该连接。

   分两种情况:

    (1) 应用程序中主动关闭该连接,即DBCPTest.java中第79行  conn.close();

     这种情况并不是手动将该连接关闭,而是将该连接交回给DBCP连接池,由连接池管理该连接。即用完连接后显示的将数据库连接提交至DBCP连接池。

    (2) 应用程序中不关闭该连接,即将DBCPTest.java中第79行  conn.close()注释掉

     这种情况DBCP配置文件dbcp.properties中的配置项(注意jar包版本,低版本中使用removeAbandoned=true配置项) 

     removeAbandonedOnMaintenance=true
        removeAbandonedOnBorrow=true

      removeAbandonedTimeout=1

      会起作用,removeAbandonedOnMaintenance=true和removeAbandonedOnBorrow=true表示DBCP连接池自动管理应程序中使用完毕的连接,removeAbandonedTimeout=1表示一个连接在程序中使用完毕后,若在1秒之内没有再次使用,则DBCP连接池回收该连接(通常removeAbandonedTimeout不会配置1,此处为了测试使用)。

    (3) 验证removeAbandonedOnMaintenance=true、removeAbandonedOnBorrow=trueremoveAbandonedTimeout=1配置项的作用

       将测试类DBCPTest.java的writeDBByDBCP(int data)方法修改为如下:

      //通过DBCP连接池写数据库
public void writeDBByDBCP(int data){
String sql = "insert into dbcp values (" + data + ")";
try {
Connection conn = KCYDBCPUtil.getConnection();
Statement stat = conn.createStatement();
stat.executeUpdate(sql);
conn.commit();
// conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}

    重新执行testWriteDBByDBCP()方法,结果如下:

    

    可见writeDBByDBCP(int data)方法修改后和修改前作用相同,说明连接使用完后,由DBCP连接池管理。

    而如果将修改配置项removeAbandonedTimeout=180,即一个连接用完后会等待180秒,超过180秒后才由DBCP连接池回收,重新执行testWriteDBByDBCP()方法,执行一段时间后报错(Cannot get a connection, pool error Timeout waiting for idle object),如下:

    

    此时,查询数据表,发现正好插入了30条数据,如下:

    

    这说明在插入第31条数据的时候报错,错误原因是连接池中没有可用的连接了。这是因为DBCP连接池初始化连接数为30,removeAbandonedTimeout设为180秒,所以30个连接用完后,程序运行还未 到180秒,程序中用完的连接都还没有被DBCP连接池回收,所以DBCP连接池中没有可用的连接了,才会在插入第31条数据时报错。

DBCP数据库连接池的简单使用的更多相关文章

  1. 【Java EE 学习 16 上】【dbcp数据库连接池】【c3p0数据库连接池】

    一.回顾之前使用的动态代理的方式实现的数据库连接池: 代码: package day16.utils; import java.io.IOException; import java.lang.ref ...

  2. java数据库连接池技术简单使用

    JDBCDemo.java: package com.itheima.jdbc; import java.sql.Connection; import java.sql.PreparedStateme ...

  3. 一次项目实践中DBCP数据库连接池性能优化

    关于数据库连接池DBCP的关注源于刚刚结束的一轮测试,测试内容是衡量某Webserver服务创建用户接口的性能.这是一款典型的tomcat应用,使用的测试工具是Grinder.DBCP作为tomcat ...

  4. DBCP数据库连接池的使用

    DBCP的简单介绍: DBCP(DataBase Connection Pool)数据库连接池,是java数据库连接池的一种,由apache开发通过数据库连接池可以让程序自动管理数据库连接的释放和断开 ...

  5. DBCP数据库连接池

    在用JDBC连接数据库的时候,需要创建对数据库的连接,这样才能执行后续的操作.然而,这样做有两个问题: 数据库允许的连接个数有限 创建连接的过程需要消耗内存和时间 所以,JDBC引入了连接池的概念.也 ...

  6. java基础之JDBC六:DBCP 数据库连接池简介

    我们之前写的代码中的数据库连接每次都是自己创建,用完以后自己close()销毁的,这样是很耗费资源的,所以我们引入DBCP DBCP简介 概述: Data Base Connection Pool, ...

  7. DBCP数据库连接池原理分析

    在比较大的项目中,需要不断的从数据库中获取数据,Java中则使用JDBC连接数据库,但是获取数据库的连接可是相当耗时的操作,每次连接数据库都获得 .销毁数据库连接,将是很大的一个开销.为了解决这种开销 ...

  8. DBCP数据库连接池初探

    1. 概述 数据库连接是很“宝贵的”,如果每次获取Connection都去创建数据库连接,使用之后就断开,再次使用又重新创建,程序效率是很低的.因为Socket连接的建立很消耗资源. 所以需要数据库连 ...

  9. 03_dbcp数据源依赖jar包,DBCP中API介绍,不同过dbcp方式使用dbcp数据库连接池,通过配置文件使用dbcp数据库连接池

     DBCP数据源 使用DBCP数据源,需要导入两个jar包 Commons-dbcp.jar:连接池的实现 Common-pool.jar:连接池实现的依赖库. 导入mysql的jar包. DBC ...

随机推荐

  1. 转:Redis和Memcache的区别分析

    Redis和Memcache的区别分析  原文链接:http://blog.csdn.net/u013474436/article/details/48632665 简单区别: 1. Redis中,并 ...

  2. 为什么排版引擎解析 CSS 选择器时一定要从右往左解析?

    首先我们要看一下选择器的「解析」是在何时进行的. 主要参考这篇「 How browsers work」(http://taligarsiel.com/Projects/howbrowserswork1 ...

  3. vue2.0路由写法

    // 0. 如果使用模块化机制编程,導入Vue和VueRouter,要调用 Vue.use(VueRouter) // 1. 定义(路由)组件. // 可以从其他文件 import 进来 var Fo ...

  4. [iOS] UIFont 设置字体

    label.font = [UIFont fontWithName:@"Arial-BoldItalicMT" size:24]; 字体名如下: Font Family: Amer ...

  5. LoadRunner对移动互联网后端服务器压力测试

    一.LoadRunner简介 LoadRunner,是惠普公司研发的一款预测系统行为和性能的负载测试工具.通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题,LoadRunner能够 ...

  6. 毕向东_Java基础视频教程第20天_IO流(15~17)

    第20天-15-IO流(打印输出流) 打印输出流:PrintWriter与PrintStream 两者的区别:Since JDK 1.4 it's possible to specify the ch ...

  7. 沉淀再出发:kafka初探

    沉淀再出发:kafka初探 一.前言 从我们接触大数据开始,可能绕在耳边的词汇里面出现的次数越来越多的就包括kfaka了.kafka的设计初衷是希望作为一个统一的信息收集平台,能够实时的收集反馈信息, ...

  8. 月报 提取/保存 到OneDrive. 并发送反馈邮件

  9. procedure of intall and setup centos 6.5

    select webserver install option,and select ,uncheck the postgresql option selected some “… platform” ...

  10. Alpha Scrum7

    Alpha Scrum7 牛肉面不要牛肉不要面 Alpha项目冲刺(团队作业5) 各个成员在 Alpha 阶段认领的任务 林志松:项目发布 陈远军.陈彬:播放器各环境的测试 项目的发布说明 本版本的新 ...