DBCP数据库连接池的简单使用

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
#url
url=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=true
removeAbandonedOnMaintenance=true
removeAbandonedOnBorrow=true
#连接在所指定的秒数内未使用才会被删除(秒)(为配合测试程序才配置为1秒)
removeAbandonedTimeout=1

  

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

 1 package dbcp;
 2
 3 import java.io.FileInputStream;
 4 import java.io.IOException;
 5 import java.sql.Connection;
 6 import java.sql.SQLException;
 7 import java.util.Properties;
 8
 9 import javax.sql.DataSource;
10
11 import org.apache.commons.dbcp2.BasicDataSourceFactory;
12
13 /**
14  * DBCP配置类
15  * @author SUN
16  */
17 public class KCYDBCPUtil {
18
19     private static Properties properties = new Properties();
20     private static DataSource dataSource;
21     //加载DBCP配置文件
22     static{
23         try{
24             FileInputStream is = new FileInputStream("config/dbcp.properties");
25             properties.load(is);
26         }catch(IOException e){
27             e.printStackTrace();
28         }
29
30         try{
31             dataSource = BasicDataSourceFactory.createDataSource(properties);
32         }catch(Exception e){
33             e.printStackTrace();
34         }
35     }
36
37     //从连接池中获取一个连接
38     public static Connection getConnection(){
39         Connection connection = null;
40         try{
41             connection = dataSource.getConnection();
42         }catch(SQLException e){
43             e.printStackTrace();
44         }
45         try {
46             connection.setAutoCommit(false);
47         } catch (SQLException e) {
48             e.printStackTrace();
49         }
50         return connection;
51     }
52
53     public static void main(String[] args) {
54         getConnection();
55     }
56 }

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

 1 package dbcp;
 2
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5
 6 public class DBConn {
 7     private static Connection conn = null;
 8
 9     //获取一个数据库连接
10     public static Connection getConnection() {
11         try {
12             Class.forName("com.mysql.jdbc.Driver");
13             DriverManager.registerDriver(new com.mysql.jdbc.Driver());
14             String dbUrl = "jdbc:mysql://127.0.0.1:3306/mydb";
15             conn = DriverManager.getConnection(dbUrl, "sa", "123456");
16 //            System.out.println("========数据库连接成功========");
17         } catch (Exception e) {
18             e.printStackTrace();
19 //            System.out.println("========数据库连接失败========");
20             return null;
21         }
22         return conn;
23     }
24 }

  4) 创建测试类DBCPTest.java

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

    3中插入数据方法如下:

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

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

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

 1 package dbcp;
 2
 3 import java.sql.Connection;
 4 import java.sql.SQLException;
 5 import java.sql.Statement;
 6
 7 import org.junit.Test;
 8
 9 public class DBCPTest {
10
11     //测试,每写一条数据前,就新建一个连接
12     @Test
13     public void testWriteDBByEveryConn() throws Exception{
14         for(int i = 0; i < 2000; i++){
15             writeDBByEveryConn(i);
16         }
17         System.out.println("DONE");
18
19     }
20
21     //测试,使用连接池,每写一条数据前,从连接池中获取一个连接
22     @Test
23     public void testWriteDBByDBCP() throws Exception{
24         for(int i = 0; i < 2000; i++){
25             writeDBByDBCP(i);
26         }
27         System.out.println("DONE");
28     }
29
30     //测试,只建一条连接,写入所有数据
31     @Test
32     public void testWriteDBByOneConn() throws Exception{
33         Connection conn = DBConn.getConnection();
34         Statement stat = conn.createStatement();
35         for(int i = 0; i < 2000; i++){
36             writeDBByOneConn(i, stat);
37         }
38         conn.close();
39         System.out.println("DONE");
40     }
41
42     //不使用连接池写数据库,每写一条数据创建一个连接
43     public void writeDBByEveryConn(int data){
44         String sql = "insert into dbcp values (" + data + ")";
45         Connection conn = DBConn.getConnection();
46         try{
47             Statement stat = conn.createStatement();
48             stat.executeUpdate(sql);
49         }catch(Exception e){
50             e.printStackTrace() ;
51         }finally{
52             try {
53                 conn.close();
54             } catch (SQLException e) {
55                 e.printStackTrace();
56             }
57
58         }
59     }
60
61     //不使用连接池写数据库,只用一个连接,写所有数据
62     public void writeDBByOneConn(int data, Statement stat){
63         String sql = "insert into dbcp values (" + data + ")";
64         try{
65             stat.executeUpdate(sql);
66         }catch(Exception e){
67             e.printStackTrace() ;
68         }
69     }
70
71     //通过DBCP连接池写数据库
72     public void writeDBByDBCP(int data){
73         String sql = "insert into dbcp values (" + data + ")";
74         try {
75             Connection conn = KCYDBCPUtil.getConnection();
76             Statement stat = conn.createStatement();
77             stat.executeUpdate(sql);
78             conn.commit();
79             conn.close();
80         } catch (SQLException e) {
81             e.printStackTrace();
82         }
83     }
84
85 } 

  测试结果如下:

  (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)方法修改为如下:

 1     //通过DBCP连接池写数据库
 2     public void writeDBByDBCP(int data){
 3         String sql = "insert into dbcp values (" + data + ")";
 4         try {
 5             Connection conn = KCYDBCPUtil.getConnection();
 6             Statement stat = conn.createStatement();
 7             stat.executeUpdate(sql);
 8             conn.commit();
 9 //            conn.close();
10         } catch (SQLException e) {
11             e.printStackTrace();
12         }
13     }

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

    

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

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

    

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

    

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

时间: 2024-10-25 19:10:30

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

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

JDBCDemo.java: package com.itheima.jdbc; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import com.itheima.pool.MyPool; public class JDBCDemo { public static void main(String[]

DBCP数据库连接池-方式2手动创建

DBCPUtils.java package com.itheima.b_dbcp; import java.sql.Connection; import java.sql.SQLException; import org.apache.commons.dbcp.BasicDataSource; public class DBCPUtils { private static BasicDataSource dataSource ; static{ try { // 手动创建连接池 dataSou

【Java EE 学习第16天】【dbcp数据库连接池】【c3p0数据库连接池】

零.回顾之前使用的动态代理的方式实现的数据库连接池: 代码: 1 package day16.utils; 2 3 import java.io.IOException; 4 import java.lang.reflect.InvocationHandler; 5 import java.lang.reflect.Method; 6 import java.lang.reflect.Proxy; 7 import java.sql.Connection; 8 import java.sql.D

DBCP数据库连接池——可适用DB2数据库

前提:     项目导入DB2的驱动jar包 驱动包 下载 >关于DBCP DBCP(DataBase connection pool),数据库连接池.是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件.单独使用dbcp需要3个包:commons-dbcp.jar,commons-pool.jar,commons-collections.jar由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据

DBCP数据库连接池和 c3p0数据库连接池的使用

DBCP数据库连接池 http://m.blog.csdn.net/article/details?id=47033595 c3p0数据库连接池的使用 http://blog.csdn.net/wushangjimo/article/details/12654491

dbcp数据库连接池属性介绍

#最大连接数量:连接池在同一时间能够分配的最大活动连接的数量,,如果设置为非正数则表示不限制,默认值8 maxActive=15 #最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,如果设置为0则不创建,默认值0 minIdle=5 #最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制,默认值8 maxIdle=10 #初始化连接数:连接池启动时创建的初始化连接数量,默认值0 initialSize=5 #连接被

DBCP数据库连接池连接mysql数据库的时候 出现连接问题

在部署的项目的时候发现两个问题 ,第一个问题不是太容易发现 ,因为我部署的时候没问题 ,但是产品的同事在跑流程的时候总是出现一个connetException异常  自己看了半天没发现什么问题 去网上查了一下 说是msql的连接默认是八个小时 第二个问题就是 自己这边的数据库 隔一段时间不用的话 会自动断开  查了一下资料 是dbcp连接mysql时出现的这个问题  实际上两个问题算是一个问题吧 自己配置了一下 这几天没报这样的错误 !算是解决了吧!  <bean id="dataSour

解决dbcp数据库连接池错误

使用dbcp数据库连接池时报错 java.lang.NoClassDefFoundError: org/apache/commons/pool2/PooledObjectFactory原因:缺少commons-pool2-2.4.2.jarcommons-dbcp2-2.1.1.jar 原文地址:http://blog.51cto.com/59465168/2071979

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

关于数据库连接池DBCP的关注源于刚刚结束的一轮测试,测试内容是衡量某Webserver服务创建用户接口的性能.这是一款典型的tomcat应用,使用的测试工具是Grinder.DBCP作为tomcat服务器常用的数据库连接池,其性能表现直接关乎应用的性能. 1.遇到的问题 当并发量增加到100时,该接口出现瓶颈,此时TPS接近400,如下图.但是服务端CPU和内存等资源并未达到瓶颈,服务器CPU使用率仅为30%,内存使用率为40%.监控到的javaMethod慢方法为incrAppAccount