• JDBC实例--工具类升级,使用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/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

  • 相关阅读:
    GO异常 | runnerw.exe: CreateProcess failed with error 21
    tab切换效果
    第一次码前端页面的经历
    开博第一天
    软件架构参考模板-软件架构设计学习第三天(原创)
    架构设计基础-软件架构设计学习第二天(非原创)
    IT架构师介绍-软件架构设计学习第一天(非原创)
    Android常见面试题学习第二天(原创)
    Android常见面试题学习第一天(原创)
    Netty简单介绍(非原创)
  • 原文地址:https://www.cnblogs.com/liuhongfeng/p/4174661.html
Copyright © 2020-2023  润新知