首页 > 代码库 > 使用Apache DBCP连接池重构DBUtility,让连接数据库更有效,更安全

使用Apache DBCP连接池重构DBUtility,让连接数据库更有效,更安全

直接使用JDBC访问数据库时,需要避免以下隐患:

1. 每一次数据操作请求都需要建立数据库连接、打开连接、存取数据和关闭连接等步骤。而建立和打开数据库连接是一件既耗资源又费时的过程,如果频繁发生这种数据库操作,势必会使系统性能下降。

2. 连接对象代表着数据库系统的连接进程,是有限的资源。如果系统的使用用户非常多,有可能超出数据库服务器的承受极限,造成系统的崩溃。

数据库连接池是解决上述问题最常用的方法。所谓连接池,即可以创建并持有数据库连接的组件。连接池可以预先创建并封装一些连接对象并将其缓存起来,当需要使用连接对象时可以向连接池“借”一个连接,用完之后将其“归还”到连接池中。

数据库连接池的主要功能如下:

1. 连接池对象的创建和释放。

2. 服务器启动时,创建指定数量的数据库连接。

3. 为用户请求提供可用连接。如果没有空闲连接,且连接数没有超出最大值,创建一个新的数据库连接。

4. 将用户不再使用的连接标识为可用连接,等待其他用户请求。

5. 当空闲的连接数过多时,释放连接对象。

连接池组件一般都需要实现JDBC规范中的javax.sql.DataSource接口。DataSource接口定义了获取连接的方法getConnection方法。

常用的连接池组件有DBCP、c3p0和proxool等,我这里是以Apache的DBCP组件为例来实现数据库连接池。

 

新建一个java项目,以及配置文件,如下:

技术分享

 

在当前工程下,导入使用DBCP组件所需的jar包,包括commons-dbcp.jar以及commons-pool.jar两个jar包,这两个jar包的名字可能会因为版本的不同,名字的最后为版本信息,例如:commons-dbcp-1.2.1.jar。

 

工具类DBUtility:

 

  1 package com.daliu.jdbc;  2   3 import java.io.IOException;  4 import java.sql.Connection;  5 import java.sql.SQLException;  6 import java.util.Properties;  7   8 import org.apache.commons.dbcp.BasicDataSource;  9 /** 10  * 工具类 11  * @author daliu_it 12  * 13  */ 14 public class DBUtility { 15     private static BasicDataSource dataSource = null; 16  17     public DBUtility() { 18     } 19     public static void init() { 20  21         Properties dbProps = new Properties(); 22         // 取配置文件可以根据实际的不同修改 23         try { 24             dbProps.load(DBUtility.class.getClassLoader().getResourceAsStream( 25                     "com/daliu/jdbc/db.properties")); 26         } catch (IOException e) { 27             e.printStackTrace(); 28         } 29  30         try { 31             String driveClassName = dbProps.getProperty("jdbc.driverClassName"); 32             String url = dbProps.getProperty("jdbc.url"); 33             String username = dbProps.getProperty("jdbc.username"); 34             String password = dbProps.getProperty("jdbc.password"); 35  36             String initialSize = dbProps.getProperty("dataSource.initialSize"); 37             String minIdle = dbProps.getProperty("dataSource.minIdle"); 38             String maxIdle = dbProps.getProperty("dataSource.maxIdle"); 39             String maxWait = dbProps.getProperty("dataSource.maxWait"); 40             String maxActive = dbProps.getProperty("dataSource.maxActive"); 41  42             dataSource = new BasicDataSource(); 43             dataSource.setDriverClassName(driveClassName); 44             dataSource.setUrl(url); 45             dataSource.setUsername(username); 46             dataSource.setPassword(password); 47  48             // 初始化连接数 49             if (initialSize != null) 50                 dataSource.setInitialSize(Integer.parseInt(initialSize)); 51  52             // 最小空闲连接 53             if (minIdle != null) 54                 dataSource.setMinIdle(Integer.parseInt(minIdle)); 55  56             // 最大空闲连接 57             if (maxIdle != null) 58                 dataSource.setMaxIdle(Integer.parseInt(maxIdle)); 59  60             // 超时回收时间(以毫秒为单位) 61             if (maxWait != null) 62                 dataSource.setMaxWait(Long.parseLong(maxWait)); 63  64             // 最大连接数 65             if (maxActive != null) { 66                 if (!maxActive.trim().equals("0")) 67                     dataSource.setMaxActive(Integer.parseInt(maxActive)); 68             } 69         } catch (Exception e) { 70             e.printStackTrace(); 71             System.out.println("创建连接池失败!请检查设置!!!"); 72         } 73     } 74  75     /** 76      * 数据库连接 77      * @return 78      * @throws SQLException 79      */ 80     public static synchronized Connection getConnection() throws SQLException { 81         if (dataSource == null) { 82             init(); 83         } 84         Connection conn = null; 85         if (dataSource != null) { 86             conn = dataSource.getConnection(); 87         } 88         return conn; 89     } 90      91     /** 92      * 关闭数据库 93      * @param conn 94      */ 95     public void closeConnection(Connection conn){ 96         if(conn!=null){ 97             try { 98                 conn.close(); 99             } catch (SQLException e) {100                 System.out.println("关闭资源失败");101                 e.printStackTrace();102             }103         }104     }105     106 }

 

 

 

重构db.properties文件,在该文件中添加创建数据库连接池所需的信息,包括初始化连接数、最大空闲连接数、大小空闲连接数、最大连接数量以及超时回收时间。该文件内容如下所示:

 1 #Oracle 2 #jdbc.driverClassName=oracle.jdbc.OracleDriver 3 #jdbc.url=jdbc:oracle:thin:@localhost:1521:orcl 4 #jdbc.username=root 5 #jdbc.password=123456 6  7 #Mysql 8 jdbc.driverClassName=com.mysql.jdbc.Driver 9 jdbc.url=jdbc:mysql://localhost:3306/csdn10 jdbc.username=root11 jdbc.password=12345612 13 dataSource.initialSize=1014 dataSource.maxIdle=2015 dataSource.minIdle=516 dataSource.maxActive=5017 dataSource.maxWait=1000

 

测试类testCase:

 1 package com.daliu.test; 2  3 import java.sql.SQLException; 4  5 import org.junit.Test; 6  7 import com.daliu.jdbc.DBUtility; 8  9 10 public class testCase {11 12     /**13      * 测试是否连接14      * @throws SQLException15      */16     @Test17     public void testgetConnection() throws SQLException{18         DBUtility db=new DBUtility();19         System.out.println(db.getConnection());20     }21 }

 

操作数据库EmpDAO类:

 1 package com.daliu.jdbc; 2 import java.sql.Connection; 3 import java.sql.ResultSet; 4 import java.sql.SQLException; 5 import java.sql.Statement; 6  7 public class EmpDAO { 8     public static void main(String[] args) { 9         EmpDAO dao = new EmpDAO();10         dao.findAll();11     }12 13    /**14     * 查询数据库表中的所有信息15     */16     public void findAll() {17         18         Connection con = null;19         Statement stmt = null;20         ResultSet rs = null;21 22         23         try {24             //1.获得连接25             con = DBUtility.getConnection();26             //2.通过Connection的createStatement()方法获取数据库操作对象Statement。27             stmt = con.createStatement();28             //3.通过调用Statement对象的executeQuery方法来执行SQL语句。29             rs = stmt30                     .executeQuery("select empno, ename, sal, hiredate from emp");31             //4.ResultSet 对象没有下一行时返回 false,因此可以在 while 循环中使用它来迭代结果集32             while (rs.next()) {33                 System.out.println(rs.getInt("empno") + ","34                         + rs.getString("ename") + "," + ","35                         + rs.getDouble("sal") + "," + rs.getDate("hiredate"));36             }37             38             39         } catch (SQLException e) {40             System.out.println("数据库访问异常!");41             throw new RuntimeException(e);42         } finally {43             try {44                 45                 //5.在finally块中,依次关闭ResultSet对象、Statement对象以及Connection对象。46                 if (rs != null) {47                     rs.close();48                 }49                 if (stmt != null) {50                     stmt.close();51                 }52                 if (con != null) {53                     con.close();54                 }55             } catch (SQLException e) {56                 System.out.println("释放资源时发生异常");57             }58         }59     }60 }

 

 

 Mysql脚本:

 1 create database csdn; 2  3 use csdn; 4  5 CREATE TABLE emp( 6     empno int(4), 7     ename VARCHAR(10), 8     job VARCHAR(9), 9     mgr int(4),10     hiredate DATE,11     sal double(7,2),12     comm double(7,2),13     deptno double(2,0)14 );15 16 INSERT INTO emp VALUES(7369,SMITH,CLERK,7902,1980-12-17,800,NULL,20);17 INSERT INTO emp VALUES(7499,ALLEN,SALESMAN,7698,1981-2-20,1600,300,30);18 INSERT INTO emp VALUES(7521,WARD,SALESMAN,7698,1981-2-22,1250,500,30);19 INSERT INTO emp VALUES(7566,JONES,MANAGER,7839,1981-4-2,2975,NULL,20);20 INSERT INTO emp VALUES(7654,MARTIN,SALESMAN,7698,1981-9-21,1250,1400,30);21 INSERT INTO emp VALUES(7698,BLAKE,MANAGER,7839,1981-5-1,2850,NULL,30);22 INSERT INTO emp VALUES(7782,CLARK,MANAGER,7839,1981-6-9,2450,NULL,10);23 INSERT INTO emp VALUES(7788,SCOTT,ANALYST,7566,1987-4-19,3000,NULL,20);24 INSERT INTO emp VALUES(7839,KING,PRESIDENT,NULL,1981-11-17,5000,NULL,10);25 INSERT INTO emp VALUES(7844,TURNER,SALESMAN,7698,1981-9-8,1500,0,30);26 INSERT INTO emp VALUES(7876,ADAMS,CLERK,7788,1987-5-27,1100,NULL,20);27 INSERT INTO emp VALUES(7900,JAMES,CLERK,7698,1981-12-1,950,NULL,30);28 INSERT INTO emp VALUES(7902,FORD,ANALYST,7566,1981-12-3,3000,NULL,20);29 INSERT INTO emp VALUES(7934,MILLER,CLERK,7782,1982-1-23,1300,NULL,10);30 31 select * from emp;

 

转载请标明:http://www.cnblogs.com/liuhongfeng/p/4174661.html

使用Apache DBCP连接池重构DBUtility,让连接数据库更有效,更安全