简介

DBCP (DatabaseConnection Pool)是Apache放下的一个依赖Jakarta commons-pool对象池机制的数据库连接池,Tomcat的数据源使用的就是DBCP。目前 DBCP有两个版本分别是1.3和1.4,其中:1.3版本对应的是JDK 1.4~1.5和JDBC 3,而1.4版本对应JDK 1.6和JDBC4,这两个功能上倒是没有什么区别。
使用DBCP会用到commons-dbcp.jarcommons-pool.jar两个包。

DBCP的工作原理是,程序首先会初始化相应的数据库连接池,以供程序访问,当某个操作需要访问数据库时,程序会首先在连接池中取得空闲连接,如没有空闲连接在创建,用完之后归还连接池,这样达到了连接的重利用,不用频繁的创建连接和销毁,从而优化程序。

DBCP常见属性有:

  • driver:数据库驱动,如 com.mysql.jdbc.Driver
  • url:数据库连接,如 jdbc:mysql://localhost:3306/testDB
  • username:数据库用户名,如 root
  • password:数据库用户名口令,如 root
  • initsize:初始化连接池大小
  • minidle:最小空闲连接
  • maxidle:最大空闲连接。以maxidle=15为例,它表示的在并发的情况下,连接池就必须从数据库中获取 15 个连接来供应程序使用,当应用连接关闭之后,由于 maxidle=10 并不是所有的连接都归还给了数据库,将会有 10 连接保存在连接池中,这时的状态就是空闲。
  • maxactive:最大连接, 表示在并发情况下最大能从数据连接池中获取的连接数
  • maxwait:最大等待时间
  • removeabandoned:是否自动回收超时连接, boolean 类型( true/false )

示例:演示DBCP数据库连接池的用法。

第一步:创建项目在其中导入mysql的驱动以及DBCP相关的jar文件,然后在项目类路径下创建一个名为dbcpcfg.properties的DBCP配置文件,具体信息如下:

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/book?useSSL=true&serverTimezone=UTC&characterEncoding=utf8
username=root
password=root
initialSize=4
maxActive=6
maxIdle=5
minIdle=2
maxWait=6000

第二步:创建DBCP工具类,具体代码如下:

public class DBUtil {
   private static DataSource dataSource;
private DBUtils() {
}
   static{
      try {
         InputStream in = DBCPUtil.class.getClassLoader()
		.getResourceAsStream("dbcpcfg.properties");//读取配置文件,初始化数据源
         Properties props = new Properties();
         props.load(in);
         dataSource = BasicDataSourceFactory.createDataSource(props);
      }  catch (Exception e) {
         throw new ExceptionInInitializerError(e);
      }
   }   
   public static DataSource getDataSource(){
      return dataSource;
   }
   public static Connection getConnection(){
      try {
         return dataSource.getConnection();
      } catch (SQLException e) {
         throw new RuntimeException("get database connection failed");
      }
   }
}

第三步:提供测试代码:

  • 对于某个特定的数据库(MySQL)来说一个DataSource最多只能产生maxActive个Connection。Connection用完之后若不释放,就会发生不够用的情况;若及时释放,则不会发生不够用的情况。
public static void main(String[] args) {
    for(int i =0;i<8;i++) {
        Connection conn = DBUtil.getConnection();
        System.out.println(i+": "+conn);
        try {
           // conn.close();   // ------ ①
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
运行测试代码,当将编号①处的代码注释起来时,在控制台中输出6个Connection,过了一会(大约6秒)程序报错关闭,如下图14.8所示;当让编号①处的代码执行时,程序会在控制台上输出10个Connection对象。
  • 对于特定的数据库(比如MySQL)来说,它能产生的DataSource数量是有限的
public static DataSource getDataSource() throws Exception {
	Properties props = new Properties();
	InputStream is = DBUtil.class.getClassLoader()
						.getResourceAsStream("dbcpcfg.properties");
	props.load(is);
	DataSource ds = BasicDataSourceFactory.createDataSource(props);
	return ds;
}
public static void main(String[] args) throws Exception {
	for (int i = 0; i < 3000; i++) {
		DataSource ds = getDataSource();
		System.out.println(i + ": " + ds.hashCode());
	}
}