码迷,mamicode.com
首页 > 数据库 > 详细

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

时间:2014-12-19 20:43:19      阅读:310      评论:0      收藏:0      [点我收藏+]

标签:

直接使用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/csdn
10 jdbc.username=root
11 jdbc.password=123456
12 
13 dataSource.initialSize=10
14 dataSource.maxIdle=20
15 dataSource.minIdle=5
16 dataSource.maxActive=50
17 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 SQLException
15      */
16     @Test
17     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 = stmt
30                     .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,让连接数据库更有效,更安全

标签:

原文地址:http://www.cnblogs.com/liuhongfeng/p/4174661.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!