记性不如烂笔头21-JAVA数据库连接池 DBCP


用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天100万访问量,数据库服务器就需要创建100万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器连接数溢出,并且用户的使用也会很慢,影响用户体验;

对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。

数据库连接池针对这些问题创建出来。数据库连接池负责分配,管理和释放数据库资源,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。

数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中, 这些数据库连接的数量是由最小数据库连接数来设定的.无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量.连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中.

 

数据库连接池的最小连接数和最大连接数的是最重要的两个参数指标。

最小连接数:是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费.

最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作

1、源代码数据源(DataSource

DataSource的实现,按其英文含义称之为数据源,数据源中都包含了数据库连接池的实现。现在很多WEB服务器(Weblogic, WebSphere, Tomcat)都提供了自带的DataSoruce的管理。

也有一些开源组织提供了数据源的其他实现,比如著名的有DBCP 数据库连接池、C3P0 数据库连接池等。

DBCP 是 Apache 软件基金组织下的开源连接池实现,要使用DBCP数据源,需要应用程序应在系统中增加如下两个 jar 文件:

 

Commons-dbcp.jar:连接池的实现

Commons-pool.jar:连接池实现的依赖库

Tomcat6.0已经以前版本的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。(tomcat7.0版本使用了自带的连接池)

 

2、DBCP必须配置的参数

Username 建立数据库连接的用户名;

Password 建立数据库连接的密码;

URL 传递给JDBC驱动的用于建立连接的URL

DriverClassName  使用的JDBC驱动的完整有效的java 类名

connectionProperties 当建立新连接时被发送给JDBC驱动的连接参数,格式必须是key=value格式

 

3、DBCP其他参数详解

initialSize  初始化连接:连接池启动时创建的初始化连接数量

maxActive 最大活动连接:连接池在同一时间能够分配的最大活动连接的数量,类似于并发量,设为0表示无限制 ,2.0版本中,已经去掉该方法,对应替代的方法为:setMaxTotal();

maxIdle 最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制。

minIdle 最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,如果设置为0则不创建

maxWait 最大建立连接等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以毫秒计数),超过时间则抛出异常,如果设置为-1表示无限等,2.0中已经去掉该方法,替代方法为:setMaxWaitMillis();

removeAbandoned  是否自动回收超时连接

removeAbandonedTimeout 设置超时时间有一个要注意的地方,超时时间=现在的时间-程序中创建Connection的时间,如果 maxActive比较大,比如超过100,那么removeAbandonedTimeout可以设置长一点比如180,也就是三分钟无响应的连接进行回收,当然应用的不同设置长度也不同。

timeBetweenEvictionRunsMillis, minEvictableIdleTimeMillis一起使用,每timeBetweenEvictionRunsMillis毫秒秒检查一次连接池中空闲的连接,把空闲时间超过minEvictableIdleTimeMillis毫秒的连接断开,直到连接池中的连接数到minIdle为止

testOnBorrow、testOnReturn、testWhileIdle,这些属性的意义是取得、返回对象和空闲时是否进行验证,检查对象是否有效,默认都为false即不验证。所以当使用DBCP时,数据库连接因为某种原因断掉后,再从连接池中取得连接又不进行验证,这时取得的连接实际已经时无效的数据库连接了。网上很多说DBCP的bug应该都是如此吧,只有把这些属性设为true,再提供_validationQuery语句就可以保证数据库连接始终有效了。

 

4、利用DBCP实现数据库连接池的源代码

package test.ffm83.commons.dbcp;

importorg.apache.commons.dbcp.BasicDataSource;

importorg.apache.commons.dbcp.BasicDataSourceFactory;

import org.apache.commons.lang.StringUtils;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Connection;

import java.util.Properties;

/* 通过dbcp连接oracle数据库

 

 *使用1.4版本实现

 

 *@author 范芳铭

 

 **/

 

public classDbcpUsage {

   private static BasicDataSource dataSource = null;

   public DbcpUsage() {

   }

   public static void init() {

 

       if (dataSource != null) {

 

            try {

 

                dataSource.close();

 

            }catch(Exception e) {

 

                e.printStackTrace();

 

            }

 

            dataSource = null;

 

       }

 

 

 

       try {

 

            Propertiesp = newProperties();

 

           p.setProperty("driverClassName","oracle.jdbc.driver.OracleDriver");

 

            p.setProperty("url","jdbc:oracle:thin:@192.168.19.1:1521:fanfangming");

 

           p.setProperty("password","ffm");

 

           p.setProperty("username","ffm");

 

           p.setProperty("maxActive","30");

 

           p.setProperty("maxIdle","10");

 

           p.setProperty("maxWait","1000");

 

           p.setProperty("removeAbandoned","false");

 

           p.setProperty("removeAbandonedTimeout", "120");

 

           p.setProperty("testOnBorrow","true");

 

           p.setProperty("logAbandoned","true");

 

 

 

            dataSource =(BasicDataSource)BasicDataSourceFactory

 

                    .createDataSource(p);

 

       }catch(Exception e) {

 

            e.printStackTrace();

 

       }

 

   }

 

 

 

   public static synchronized ConnectiongetConnection() throwsSQLException{

 

       if (dataSource == null) {

 

            init();

 

       }

 

       Connectionconn = null;

 

       if (dataSource != null) {

 

            conn= dataSource.getConnection();

 

       }

 

       return conn;

 

   }

 

 

 

   public static void main(String[] args) throws Exception {

 

       Connectioncon = null;

 

       try {

 

            con= DbcpUsage.getConnection();

 

            Stringsql = " select sysdate from dual";

 

            PreparedStatement ps =con.prepareStatement(sql);

 

            ResultSet rs = ps.executeQuery();

 

            while (rs.next()) {

 

                String value =rs.getString("sysdate");

 

               System.out.println(StringUtils.center(value+",数据库连接成功", 50, "-"));

 

            }

 

       }catch(Exception e) {

 

            e.printStackTrace();

 

       }finally{

 

            if (con != null) {

 

                con.close();

 

            }

 

       }

 

   }

 

}

 

运行如下:

 

----------2014-12-1612:38:32.0,数据库连接成功-----------

5、运行结果

运行如下:

 

----------2014-12-1612:38:32.0,数据库连接成功-----------

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。