java数据库连接池dbcp的使用

近年来,随着 Internet/Intranet 建网技术的飞速发展和在世界范围内的迅速普及,计算机

  应用程序已从传统的桌面应用转到 Web 应用。基于 B/S(Browser/Server)架构的 3 层开发模式逐渐代替 C/S(Client/Server)架构的开发模式,成为开发企业级应用和电子商务普遍採用的技术。

在 Java 语言中,JDBC(Java DataBase Connection)是应用程序与数据库沟通的桥梁,

  即 Java 语言通过 JDBC 技术訪问数据库。JDBC 是一种“开放”的方案,它为数据库应用开发者﹑数据库前台工具开发者提供了一种标准的应用程序设计接口,使开发者能够用纯 Java 语言编写完整的数据库应用程序。JDBC 提供两种 API,各自是面向开发者的 API 和面向底层的 JDBC 驱动程序 API,底层主要通过直接的 JDBC 驱动和 JDBC-ODBC 桥驱动实现与数据库的连接。

  一般来说,Java 应用程序訪问数据库的过程是:

  ①装载数据库驱动程序;

  ②通过 JDBC 建立数据库连接;

  ③訪问数据库,运行 SQL 语句;

  ④断开数据库连接。

JDBC 作为一种数据库訪问技术,具有简单易用的长处。但使用这样的模式进行 Web 应用
  程序开发,存在非常多问题:首先,每一次 Web 请求都要建立一次数据库连接。建立连接是一个费时的活动,每次都得花费 0.05s~1s 的时间,并且系统还要分配内存资源。这个时间对于一次或几次数据库操作,也许感觉不出系统有多大的开销。但是对于如今的 Web 应用,尤其是大型电子商务站点,同一时候有几百人甚至几千人在线是非常正常的事。在这样的情况下,频繁的进行数据库连接操作势必占用非常多的系统资源,站点的响应速度必然下降,严重的甚至会造成 server 的崩溃。不是危言耸听,这就是制约某些电子商务站点发展的技术瓶颈问题。其次,对于每一次数据库连接,使用完后都得断开。否则,假设程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,终于将不得不重新启动数据库。还有,这样的开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,server 崩溃。

由上面的分析能够看出,问题的根源就在于对数据库连接资源的低效管理。我们知道,

  对于共享资源,有一个非常著名的设计模式:资源池(Resource Pool)。该模式正是为了解决资源的频繁分配﹑释放所造成的问题。为解决上述问题,能够採用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当须要建立数据库连接时,仅仅需从“缓冲池”中取出一个,使用完成之后再放回去。我们能够通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们能够通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑測试及性能调整提供根据。
dbcp 数据库连接池代码使用例如以下:

package util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.log4j.Logger;

/**

  • Description: 数据库连接池类

  • @filename DataSourceFactory.java

  • @date 2013 年 8 月 21 日 19:47:21

  • @author Herman.Xiong

  • @version 1.0

  • Copyright (c) 2013 Company,Inc. All Rights Reserved.
    */
    public class DataSourceFactory {
    private static Logger log = Logger.getLogger(DataSourceFactory.class);
    private static BasicDataSource bs = null;
    public static String driver,url,userName,password;

    /**

    • 创建数据源
    • @return
      /
      public static BasicDataSource getDataSource() throws Exception{
      if(bs==null){
      log.info("数据库连接信息:[driver:"+driver+",url:"+url+",userName:"+userName+",password:"+password+"]");
      bs = new BasicDataSource();
      bs.setDriverClassName(driver);
      bs.setUrl(url);
      bs.setUsername(userName);
      bs.setPassword(password);
      bs.setMaxActive(200);// 设置最大并发数
      bs.setInitialSize(30);// 数据库初始化时,创建的连接个数
      bs.setMinIdle(50);// 最小空暇连接数
      bs.setMaxIdle(200);// 数据库最大连接数
      bs.setMaxWait(1000);
      bs.setMinEvictableIdleTimeMillis(60
      1000);// 空暇连接 60 秒中后释放
      bs.setTimeBetweenEvictionRunsMillis(5601000);//5 分钟检測一次是否有死掉的线程
      bs.setTestOnBorrow(true);
      }
      return bs;
      }

    /**

    • 释放数据源
      */
      public static void shutDownDataSource() throws Exception{
      if(bs!=null){
      bs.close();
      }
      }

    /**

    • 获取数据库连接
    • @return
      */
      public static Connection getConnection(){
      Connection con=null;
      try {
      if(bs!=null){
      con=bs.getConnection();
      }else{
      con=getDataSource().getConnection();
      }
      } catch (Exception e) {
      log.error(e.getMessage(), e);
      }
      return con;
      }

    /**

    • 关闭连接
      */
      public static void closeCon(ResultSet rs,PreparedStatement ps,Connection con){
      if(rs!=null){
      try {
      rs.close();
      } catch (Exception e) {
      log.error("关闭结果集 ResultSet 异常!"+e.getMessage(), e);
      }
      }
      if(ps!=null){
      try {
      ps.close();
      } catch (Exception e) {
      log.error("预编译 SQL 语句对象 PreparedStatement 关闭异常!"+e.getMessage(), e);
      }
      }
      if(con!=null){
      try {
      con.close();
      } catch (Exception e) {
      log.error("关闭连接对象 Connection 异常!"+e.getMessage(), e);
      }
      }
      }
      }