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=true和removeAbandonedTimeout=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条数据时报错。

java连接池 dbcp 样例_DBCP数据库连接池的简单使用相关推荐

  1. javaweb mysql 连接池 c3p0 配置_JavaWeb基础—数据库连接池DBCP、C3P0

    一.基本概念 数据库连接池负责分配.管理和释放数据库连接 数据库连接池:(池用map来实现居多) 用处:为了可重用(销毁创建麻烦,开销大)(招培训老师的例子) 二.编写实现数据库连接池 池参数: 初识 ...

  2. weblogic连接池不释放问题解决_数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决...

    作者:sneak 链接https://juejin.im/post/5ef800636fb9a07e66233884 来源:掘金 问题现象 在某个工作日,突然收到线上的服务告警,有大量的请求延时产生, ...

  3. mysql连接池_数据库技术:数据库连接池,Commons DbUtils,批处理,元数据

    Database Connection Pool Introduction to Database Connection Pool 实际开发中"获得连接"或"释放资源&q ...

  4. mysql连接池和最大连接数_数据库连接池和mysql的最大连接数的区别

    什么叫做数据库连接池 连接池的作用是什么? 数据库连接池,简称dbcp database connection pool 存在意义: 数据库的连接是非常耗费系统资源的,一个应用通常都是需要与数据库打交 ...

  5. JAVA的输入输出基本操作样例

    这些类的继承关系有些类似,弄一个作为样例,理解一下其中的机制. package cc.openhome;import java.io.*;public class Member {private St ...

  6. jsp获取连接池的实时连接数_数据库连接池原理分析及模拟实现

    数据库访问 访问数据库主要有以下几个步骤: 加载数据库驱动 创建数据库连接 执行访问操作并处理执行结果 关闭连接,释放资源 在每一次请求数据库都要经历上述过程,创建连接和释放资源也都是些重复性的动作, ...

  7. c#打开数据库连接池的工作机制_数据库连接池-tomcat-jdbc使用笔记

    现在 主流的数据库连接池有:Proxool.C3P0.DBCP.tomcat-jdbc.Druid.其中tomcat-jdbc是tomcat服务器比较可靠的 数据库连接池. Tomcat 在 7.0 ...

  8. eclipse链接mysql数据池配置_Tomcat+mysql+eclipse数据库连接池配置

    一.开发工具 1.tomcat版本:tomcat5.5.27 2.mysql版本:mysql 5.1 3.数据库驱动程序:mysql-connector-java-5.1.9 4.eclipse版本: ...

  9. c#打开数据库连接池的工作机制_c#数据库连接池的用法

    我为什么喜欢用C#来做并发编程 题记:就语言和运行时层面,C#做并发编程一点都不弱,缺的是生态和社区. 硅谷才女朱赟(我的家门)昨天发了一篇文章<为什么用 Java -- 关于并发编程>, ...

最新文章

  1. KVM中I/O虚拟化介绍(五)
  2. 阿里达摩院自主研发AI芯片 布局“中国芯”
  3. QT乱码总结1.Unicode 和 UTF-8
  4. IDEA 15款神级良心插件强烈推荐收藏
  5. [翻译]More C++ Idioms - 类成员检测器
  6. restful 风格 web api规范
  7. ERROR Could not find value for key log4j.appender.Console
  8. matlab 实用快捷键
  9. 大数据系统体系架构(含图示)
  10. 逆向PPTV视频真实播放地址全过程(Java版)
  11. 合天网安实验室CTF-解密200-找茬游戏
  12. IReport 图形化报表开发工具
  13. 杨绛先生70句金句,请珍藏
  14. 微信小程序系列(7)如何用微信小程序写一个论坛?贴心代码详解(五)删帖页【完结篇】
  15. 无法引导Win11卡在GNU GRUB界面
  16. Unity涂鸦【1】——基于Vectrosity的屏幕涂鸦和白板涂鸦的简单实现
  17. 微火的腾讯共享wifi项目是什么?这个项目有前景吗?
  18. 【ICML 2020对比学习论文解读】SimCLR: A Simple Framework for Contrastive Learning of Visual Representations
  19. Android自适应大小和屏幕
  20. oracle创建record,oracle record | 学步园

热门文章

  1. Microsoft Visual Studio 2010 Ultimate 正式版注册码
  2. python表情包多样化图形化聊天室_如何用python绘制一系列三维的逗比风格表情包...
  3. 开源软件为什么要有授权(License)
  4. 巫师3怎么释放替换法印_巫师3新手怎么用法印 巫师3新手法印用法-游侠网
  5. golang 实现不定数量企微群机器人消息通知 顺序必须一致 并不超过群机器人消息每分钟提醒上限20条
  6. 关于X射线球管的参数
  7. 深度学习框架比较(Caffe, TensorFlow, MXNet, Torch, Theano)
  8. 打不开计算机 在任务栏里显示,为什么我桌面上的我的电脑、文件夹打开后只有在任务栏显示,而却打不开呢...
  9. 【Vue】相关生态——Vue Router路由
  10. Lists.newArrayListWithExpectedSize( int estimatedSize)