当前位置:Gxlcms > 数据库问题 > DBCP数据库连接池的简单使用

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

时间:2021-07-01 10:21:17 帮助过:2人阅读

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条数据时报错。

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

标签:

人气教程排行