Introduction of Java Database Connection Pool DBCP


DBCP (Database connection pooling) is owned by Apache Commons 1 sub-project under the project, providing connection pool function; This article mainly introduces the basic use of DBCP, and the software versions used in this article: Java 1.8.0_191、DBCP 2.9.0、Spring Boot 2.3. 12. RELEASE.

1. Configuration parameters

参数描述
username用户名
password密码
url连接 url
driverClassName驱动名称
connectionProperties

连接属性,格式为: [propertyName=property;]*
"user" and "password" 将被除外,所以在此不需要包含这两个属性。

参数默认值描述
 defaultAutoCommit 驱动的默认值 是否自动提交
 defaultReadOnly 驱动的默认值 是否只读
 defaultTransactionIsolation 驱动的默认值

默认的事务隔离级别
NONE、READ_COMMITTED、READ_UNCOMMITTED、
REPEATABLE_READ、SERIALIZABLE

 defaultCatalog 

默认的 catalog。(目录,类似于模式名,但比模式名更加抽象;
Oracle,MySQL 不支持,MS SQL Server = 数据库名)

 cacheState true 是否缓存状态信息
 defaultQueryTimeout null 默认查询时间
 enableAutoCommitOnReturn true 连接归还到池时,是否设置为自动提交
 rollbackOnReturn true

如果设置为 true,则连接归还到连接池时,
如果 auto commit=true 且 read-only=false,则会自动执行1次 rollback()。

 参数默认值 描述
 initialSize 0初始连接数
 maxTotal 8最大连接数;负数表示没有限制
 maxIdle 8最大空闲连接数,多余的空闲连接将被释放;负数表示没有限制
 minIdle 0最小空闲连接数,如果不足则新的空闲连接将被创建。
 maxWaitMillis indefinitely从连接池获取连接,最大等待时间,超过该时间将抛出异常;-1 表示无限期
参数默认值描述
validationQuery 

连接池返回连接给调用者前用来校验的查询sql。
如果指定,则这个查询 SQL 必须至少返回1行数据;如果没有指定,则通过调用 isValid() 方法进行校验。

validationQueryTimeoutno timeout验证查询超时时间(秒)。如果设置为正数,那么通过 setQueryTimeOut()方法来设置查询的超时时间。
testOnCreatefalse连接创建后,是否验证有效性
testOnBorrowtrue从连接池获取连接时,是否验证有效性
testOnReturnfalse连接返回连接池时,是否验证有效性
testWhileIdlefalse连接空闲时,是否验证有效性;如果验证失败,则丢弃该连接。
timeBetweenEvictionRunsMillis-1校验空闲连接的时间周期,非正表示不验证
numTestsPerEvictionRun3每次校验空闲连接的个数
minEvictableIdleTimeMillis1000 * 60 * 30空闲连接至少多长时间后,才会被校验
softMinEvictableIdleTimeMillis-1空闲连接至少多长时间后,才会被校验;还需满足"空闲连接数>=minIdle"
maxConnLifetimeMillis-1连接存活的最大时间;如果设置为非正数,则存活时间是无限的
logExpiredConnectionstrue过期的连接被连接池关闭时,是否写日志
connectionInitSqlsnull连接第1次创建时,执行的初始化 SQL
lifotruetrue 表示获取连接时将返回最后返还连接池的连接(后进先出);false,则相反(先进先出)。
参数默认值描述
poolPreparedStatementsfalse预编译语句是否池化
maxOpenPreparedStatementsunlimited最大打开的预处理语句,负数表示没有限制
参数默认值描述
accessToUnderlyingConnectionAllowedfalse是否允许访问底层连接

If allowed, you can use the following code to access the underlying connection:

Connection conn = ds.getConnection();

Connection dconn = ((DelegatingConnection) conn).getInnermostDelegate();

...

conn.close()
参数默认值描述
removeAbandonedOnMaintenance
removeAbandonedOnBorrow
 false

是否删除泄露的连接;如果超过1个活动连接未使用的时间超过 removeAbandonedTimeout,则是1个泄露的连接。
创建 Statement,PreparedStatement,CallableStatement 或使用这些对象执行1个查询都会重置连接的上传使用时间。
removeAbandonedOnMaintenance:空闲连接校验时是否回收泄露的连接,要使启用该设置需把 timeBetweenEvictionRunsMillis 设置为整数
removeAbandonedOnBorrow:从连接池获取连接时是否回收泄露的连接,要使启用该设置还需满足 'getNumActive() > getMaxTotal() - 3 and getNumIdle() < 2'

removeAbandonedTimeout 300 连接泄露的超时时间(秒)
logAbandonedfalse 连接删除时是否打印堆栈信息
abandonedUsageTrackingfalse如果设置为 true,数据库连接每执行1个方法都会打印堆栈信息
参数默认值描述
fastFailValidationfalse

是否快速失败验证;如果设置为 true,当发生致命异常时,不再执行 isValid(),也不去执行验证查询语句。致命的异常码有:
57P01 (ADMIN SHUTDOWN)
57P02 (CRASH SHUTDOWN)
57P03 (CANNOT CONNECT NOW)
01002 (SQL92 disconnect error)
JZ0C0 (Sybase disconnect error)
JZ0C1 (Sybase disconnect error)
Any SQL_STATE code that starts with "08"
要覆盖默认的异常代码,可以设置 disconnectionSqlCodes 属性。

disconnectionSqlCodesnull自定义异常代码
jmxName 注册连接池的 jmx 名称

For detailed configuration instructions, please refer to the official website document: http://commons.apache.org/proper/commons-dbcp/configuration.html .

2. Use

2.1. Direct use

2.1. 1, Introducing dependencies

<dependency>

  <groupId>org.apache.commons</groupId>

  <artifactId>commons-dbcp2</artifactId>

  <version>2.9.0</version>

</dependency>

2.1. 2. Use examples

package com.abc.demo.general.dbpool;

import org.apache.commons.dbcp2.BasicDataSource;

import java.sql.Connection;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

public class DBCPCase {

    public static void main(String[] args) {

        BasicDataSource basicDataSource = new BasicDataSource();

        basicDataSource.setUrl("jdbc:mysql://10.40.9.11:3306/mydb?useUnicode=true&characterEncoding=UTF-8");

        basicDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");

        basicDataSource.setUsername("root");

        basicDataSource.setPassword("123456");

        basicDataSource.setMaxTotal(20);

        basicDataSource.setMinIdle(5);

        Connection connection = null;

        Statement st = null;

        ResultSet rs  = null;

        try {

            connection = basicDataSource.getConnection();

            st = connection.createStatement();

            rs = st.executeQuery("select version()");

            if (rs.next()) {

                System.out.println(rs.getString(1));

            }

        } catch (SQLException e) {

            e.printStackTrace();

        } finally {

            close(connection);

        }

        try {

            // In actual use 1 Generally, the data source is initialized when the application starts, and the application obtains the connection from the data source; The data source is not closed.

            basicDataSource.close();

        } catch (SQLException e) {

            e.printStackTrace();

        }

    }



    private static void close(Connection connection) {

        if (connection != null) {

            try {

                connection.close();

            } catch (SQLException e) {

                e.printStackTrace();

            }

        }

    }

}

2.2. Used in SpringBoot

2.2. 1, introducing dependencies

<parent>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-parent</artifactId>

    <version>2.3.12.RELEASE</version>

    <relativePath />

</parent>

<dependencies>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework</groupId>

        <artifactId>spring-jdbc</artifactId>

    </dependency>

    <dependency>

        <groupId>org.apache.commons</groupId>

        <artifactId>commons-dbcp2</artifactId>

        <version>2.9.0</version>

    </dependency>

    <dependency>

        <groupId>mysql</groupId>

        <artifactId>mysql-connector-java</artifactId>

    </dependency>

</dependencies>

2.2. 2, single data source

application. yml configuration:

spring:

  datasource:

    driver-class-name: com.mysql.cj.jdbc.Driver

    url: jdbc:mysql://10.40.9.11:3306/myDb?useUnicode=true&characterEncoding=UTF-8

    username: root

    password: 123456

    type: org.apache.commons.dbcp2.BasicDataSource

    dbcp2:

      max-total: 20

      max-idle: 5

Use:

@Autowired

private DataSource dataSource;

2.2. 3, Multiple Data Sources

application. yml configuration:

spring:

  datasource:

    dbcp2:

      db1:

        driver-class-name: com.mysql.cj.jdbc.Driver

        url: jdbc:mysql://10.40.9.11:3306/myDb?useUnicode=true&characterEncoding=UTF-8

        username: root

        password: 123456

        max-total: 20

        max-idle: 5

      db2:

        driver-class-name: com.mysql.cj.jdbc.Driver

        url: jdbc:mysql://10.40.9.12:3306/myDb?useUnicode=true&characterEncoding=UTF-8

        username: root

        password: 123456

        max-total: 20

        max-idle: 5

Data source configuration class:

package com.abc.demo.config;

import org.apache.commons.dbcp2.BasicDataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.boot.jdbc.DataSourceBuilder;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;



import javax.sql.DataSource;



@Configuration

public class DataSourceConfig {

    @Bean("dataSource1")

    @ConfigurationProperties(prefix = "spring.datasource.dbcp2.db1")

    public DataSource dataSource1() {

        return DataSourceBuilder.create().type(BasicDataSource.class).build();

    }

    @Bean("dataSource2")

    @ConfigurationProperties(prefix = "spring.datasource.dbcp2.db2")

    public DataSource dataSource2() {

        return DataSourceBuilder.create().type(BasicDataSource.class).build();

    }

}

Use:

@Autowired

@Qualifier("dataSource1")

private DataSource dataSource1;

@Autowired

@Qualifier("dataSource2")

private DataSource dataSource2;