DBCP(DataBase connection pool),数据库连接池。是 apache 上的一个 java 连接池项目。由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。
也是 tomcat、hibernate等开源工具使用的连接池组件。
DBCP版本已经整体升级到2.0时代,并且在jar包上做了升级,诸如org.apache.commons.dbcp2.BasicDataSource。
Jar包为:commons-dbcp2-2.0.1.jar
- DBCP 2.0.1 for JDBC 4.1 (Java 7+)
- DBCP 1.4 for JDBC 4 (Java 6)
- DBCP 1.3 for JDBC 3 (Java 1.4 and Java 5)
必须配置的参数
Username 建立数据库连接的用户名;
Password 建立数据库连接的密码;
URL 传递给JDBC驱动的用于建立连接的URL
DriverClassName 使用的JDBC驱动的完整有效的java 类名
connectionProperties 当建立新连接时被发送给JDBC驱动的连接参数,格式必须是key=value格式
连接池相关配置
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语句就可以保证数据库连接始终有效了。
一个普通的简单示例:
package test.ffm83.commons.dbcp;
import org.apache.commons.dbcp.BasicDataSource;
import org.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 ";
PreparedStatementps = con.prepareStatement(sql);
ResultSetrs = ps.executeQuery();
while (rs.next()) {
Stringvalue = 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,数据库连接成功-----------