JDBC的连接池使用
文章目录
传统的 JDBC 编程在处理数据库连接时,每次与数据库交互都需要创建新的连接,使用完后再关闭连接,这一过程在高并发场景下会导致系统性能急剧下降。为了解决这一问题,数据库连接池技术应运而生。连接池预先创建并管理一定数量的数据库连接,应用程序可直接从连接池中获取和归还连接,避免了频繁创建和销毁连接带来的性能开销。本文将介绍 JDBC 连接池的基本概念、工作原理以及常见的连接池实现。
1. 基本介绍
1.1 连接池定义
数据库连接池是一种用于管理数据库连接的技术。数据库连接池是一个容器,它预先创建并管理一定数量的数据库连接。应用程序需要与数据库进行交互时,直接从连接池中获取一个可用的连接,使用完毕后将连接归还给连接池,而不是直接关闭连接。这样,连接池中的连接可以被重复使用,避免了频繁创建和销毁连接带来的性能开销。
- 在传统的 JDBC 编程中,每次与数据库交互时都需要创建一个新的数据库连接,使用完后再关闭连接。创建和销毁连接的过程是非常消耗资源和时间的,尤其是在高并发的场景下,频繁地创建和销毁连接会导致系统性能急剧下降。
- 连接池技术的核心思想是预先创建一定数量的数据库连接,并将这些连接存储在一个 “池” 中。当应用程序需要与数据库交互时,直接从连接池中获取一个可用的连接,使用完后再将连接归还给连接池,而不是直接关闭连接。这样就避免了频繁创建和销毁连接带来的性能开销。
1.2 工作原理的介绍
数据库连接池的工作原理主要涉及初始化、获取连接、使用连接、归还连接以及连接管理等多个关键环节。
- 初始化连接池:在应用程序启动时,连接池会根据配置参数创建一定数量的数据库连接,并将这些连接存储在连接池中。
- 获取连接:当应用程序需要与数据库进行交互时,会向连接池请求一个可用的连接。连接池会从空闲连接列表中取出一个连接分配给应用程序。如果没有空闲连接,且连接池中的连接数量未达到最大连接数,连接池会创建一个新的连接;如果已达到最大连接数,则应用程序可能需要等待,直到有连接被释放。
- 使用连接:应用程序使用从连接池获取的连接执行数据库操作,如查询、插入、更新等。
- 归还连接:应用程序完成数据库操作后,将连接归还给连接池,而不是关闭连接。连接池会将该连接标记为空闲状态,以便下次使用。
- 连接管理:连接池会定期检查连接的状态,对于长时间空闲的连接进行回收,对于无效的连接进行清理和重新创建,以保证连接池中的连接都是可用的。
2. 常见的连接池
2.1 DBCP 连接池
DBCP(Database Connection Pool)是 Apache 组织开发的开源连接池,是 Tomcat 服务器默认使用的连接池。它的配置相对简单,提供了基本的连接池功能,能满足一般应用的需求。
【优点】
- 配置简单:对于初学者或者简单的项目而言,DBCP 的配置较为容易上手,相关文档资料丰富。
集成度高:与 Apache 相关项目(如 Tomcat)的集成度良好。
【缺点】
- 性能欠佳:在高并发场景下,其性能表现不如一些新兴的连接池。
- 功能有限:缺乏一些高级特性,例如对连接的监控和管理功能相对薄弱。
适用于对性能要求不高、并发量较小的小型项目。
如何使用
DBCP 连接池依赖该组织下的另一个开源系统:Common-pool。如需使用该连接池实现,应在系统中增加两个 jar 文件:
- Commons-dbcp.jar:连接池的实现
- Commons-pool.jar:连接池实现的依赖库
Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。
- 引入依赖jar包
DBCP(Database Connection Pool)有两个主要版本,DBCP 1.x 和 DBCP 2.x。
DBCP 2.x:访问 Apache Commons DBCP 2 发布页面,选择合适的版本下载对应的commons-dbcp2-x.x.x.jar文件。DBCP 1.x:虽然 DBCP 1.x 已不再维护,但你仍可以从一些镜像站点或旧版本仓库中找到commons-dbcp-1.4.jar文件。
因为找着比较繁琐,所以我一般从 Maven 中央仓库https://central.sonatype.com/下载。
- 在搜索框中输入
commons-dbcp2(DBCP 2.x)或commons-dbcp(DBCP 1.x)。选择合适的版本,然后点击下载对应的 JAR 包。- DBCP 2.x 依赖于
commons-pool2,而 DBCP 1.x 依赖于commons-pool。也可以按照上述方法下载使用。
- 配置文件
在同级目录下创建 dbcp.properties 配置文件,也可以在其他位置,只不过需要在使用的时候注意一下路径。
# 数据库连接信息
jdbc.url=jdbc:mysql://localhost:3306/database
jdbc.username=username
jdbc.password=password
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
# 连接池配置
dbcp.initialSize=5
dbcp.minIdle=5
dbcp.maxIdle=10
dbcp.maxTotal=20
- 代码加载配置文件实现
public class DBCPConfigFileExample {
public static void main(String[] args) {
try {
// 1. 加载配置文件
Properties properties = new Properties();
InputStream inputStream = new FileInputStream("src/main/resources/dbcp.properties");
properties.load(inputStream);
// 2. 创建数据源
DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
// 3. 获取数据库连接
Connection connection = dataSource.getConnection();
// 4. 关闭连接
connection.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭数据源
try {
if (connection != null) {
connection.close();
}
dataSource.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
- 常见的 DBCP 连接池配置参数及说明
| 参数名 | 说明 | 示例值 |
|---|---|---|
driverClassName | 数据库驱动类名,用于指定连接数据库所需的驱动程序。 | com.mysql.cj.jdbc.Driver |
url | 数据库连接的 URL,包含数据库的地址、端口、数据库名等信息。 | jdbc:mysql://localhost:3306/mydb |
username | 连接数据库使用的用户名。 | root |
password | 连接数据库使用的密码。 | 123456 |
initialSize | 连接池初始化时创建的连接数量。 | 5 |
maxTotal | 连接池中允许的最大连接数量。超过该数量,新的连接请求将被阻塞,直到有连接被释放。 | 20 |
maxIdle | 连接池中允许保持空闲状态的最大连接数量。超过此数量的空闲连接会被释放。 | 10 |
minIdle | 连接池中至少要保持的空闲连接数量。当空闲连接数少于该值时,连接池会创建新的连接。 | 2 |
maxWaitMillis | 获取连接时的最大等待时间(以毫秒为单位)。如果在该时间内没有可用连接,将抛出异常。 | 5000 |
testOnBorrow | 在从连接池获取连接时,是否进行连接有效性测试。开启此参数会降低性能,但能保证获取到的连接是有效的。 | true |
testOnReturn | 在将连接归还到连接池时,是否进行连接有效性测试。开启此参数会降低性能。 | false |
testWhileIdle | 在连接空闲时,是否进行连接有效性测试。建议开启,不影响性能且能保证连接的有效性。 | true |
timeBetweenEvictionRunsMillis | 连接池进行空闲连接回收的时间间隔(以毫秒为单位)。 | 60000 |
minEvictableIdleTimeMillis | 连接在池中保持空闲状态的最小时间(以毫秒为单位),超过该时间的空闲连接会被回收。 | 180000 |
validationQuery | 用于验证连接有效性的 SQL 查询语句。当 testOnBorrow、testOnReturn 或 testWhileIdle 开启时,会执行该查询。 | SELECT 1 |
numTestsPerEvictionRun | 在每次空闲连接回收操作中,检查的连接数量。 | 3 |
removeAbandonedTimeout | 连接被标记为废弃的超时时间(以秒为单位)。如果一个连接在该时间内未被使用,会被认为是废弃连接并被回收。 | 180 |
removeAbandoned | 是否开启废弃连接回收功能。开启后,长时间未使用的连接会被回收。 | true |
logAbandoned | 在回收废弃连接时,是否记录日志。开启此参数可帮助排查连接泄漏问题。 | true |
2.2 C3P0 连接池
C3P0 是一个开源的 JDBC 连接池,支持 JDBC3 规范和 JDBC2 的标准扩展。它功能丰富,提供了连接池监控、自动回收空闲连接等高级特性。
【优点】
- 功能丰富:具备多种高级配置选项,如连接池监控、自动回收空闲连接等,能更好地适应复杂的应用场景。
- 稳定性好:在长时间运行的项目中,C3P0 表现出较好的稳定性。
【缺点】
- 配置复杂:相对较多的配置选项使得配置过程较为复杂,对于新手不太友好。
- 性能一般:相较于一些新兴的连接池,其性能表现一般。
适用于对连接管理功能有较高要求、对性能要求不是特别苛刻的项目。
如何使用
- 引入依赖jar包
可以手动从 Maven 中央仓库下载 C3P0 的 JAR 包。打开Maven 中央仓库https://central.sonatype.com/,在搜索框中输入 com.mchange:c3p0,在搜索结果中选择合适的版本,在详情页面中,找到 Files 部分,下载 c3p0-<version>.jar 文件。
此外,C3P0 依赖于
mchange-commons-java库,你也需要下载该库的 JAR 包。在 Maven 中央仓库中搜索com.mchange:mchange-commons-java,选择与 C3P0 版本兼容的mchange-commons-java-<version>.jar文件进行下载。
- 配置文件
在同级目录下创建 c3p0-config.xml 配置文件,也可以在其他位置,只不过需要在使用的时候注意一下路径。
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/yourdatabase</property>
<property name="user">yourusername</property>
<property name="password">yourpassword</property>
<property name="initialPoolSize">5</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
<property name="maxIdleTime">3000</property>
</default-config>
</c3p0-config>
- 代码加载配置文件实现
public class C3P0ConfigFileExample {
public static void main(String[] args) {
// 创建数据源,会自动加载 c3p0-config.xml 中的默认配置
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 获取数据库连接
Connection connection = dataSource.getConnection();
// 关闭连接
connection.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭数据源
try {
if (connection != null) {
connection.close();
}
dataSource.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
- 常见的 C3P0 连接池配置参数及说明
| 参数名 | 说明 | 示例值 |
|---|---|---|
driverClass | 数据库驱动类的全限定名,用于加载数据库驱动程序。 | com.mysql.cj.jdbc.Driver |
jdbcUrl | 数据库连接的 URL,包含数据库的地址、端口、数据库名等信息。 | jdbc:mysql://localhost:3306/mydb |
user | 连接数据库使用的用户名。 | root |
password | 连接数据库使用的密码。 | 123456 |
initialPoolSize | 连接池初始化时创建的连接数量。 | 5 |
minPoolSize | 连接池中保持的最小连接数量。当连接池中的连接数少于该值时,会创建新的连接。 | 3 |
maxPoolSize | 连接池中允许的最大连接数量。当连接数达到该值时,新的连接请求将被阻塞,直到有连接被释放。 | 20 |
maxIdleTime | 连接在连接池中保持空闲状态的最大时间(以秒为单位)。超过该时间的空闲连接会被关闭。 | 300 |
maxStatements | 连接池中缓存的最大 SQL 语句数量。 | 100 |
maxStatementsPerConnection | 每个连接中缓存的最大 SQL 语句数量。 | 20 |
acquireIncrement | 当连接池中的连接数量不足时,每次增加的连接数量。 | 2 |
idleConnectionTestPeriod | 连接池检查空闲连接的时间间隔(以秒为单位)。定期检查以确保连接的有效性。 | 60 |
acquireRetryAttempts | 在获取连接失败时,重试的次数。 | 3 |
acquireRetryDelay | 每次重试获取连接的间隔时间(以毫秒为单位)。 | 1000 |
breakAfterAcquireFailure | 如果设置为 true,当获取连接失败达到 acquireRetryAttempts 次数后,连接池将停止尝试获取新连接。 | false |
testConnectionOnCheckout | 在从连接池获取连接时,是否进行连接有效性测试。开启此参数会降低性能,但能保证获取到的连接是有效的。 | false |
testConnectionOnCheckin | 在将连接归还到连接池时,是否进行连接有效性测试。 | true |
preferredTestQuery | 用于测试连接有效性的 SQL 查询语句。当 testConnectionOnCheckout 或 testConnectionOnCheckin 开启时,会执行该查询。 | SELECT 1 |
2.3 HikariCP 连接池
HikariCP 是一个高性能的 JDBC 连接池,设计目标是实现极致的性能和低延迟。它在开源社区中非常受欢迎,许多现代 Java 框架(如 Spring Boot)默认使用 HikariCP 作为连接池。
【优点】
- 性能卓越:通过优化代码结构和算法,HikariCP 的性能在众多连接池中表现突出,资源消耗低。
- 启动速度快:能够快速地初始化连接池,减少应用程序的启动时间。
- 代码简洁:代码量少,维护成本低。
【缺点】
- 配置选项少:相对其他连接池,其配置选项较少,对于有特殊需求的场景可能不够灵活。
适用于对性能要求极高、追求低延迟的高并发项目。
如何使用
- 引入依赖jar包
从 Maven 中央仓库 https://central.sonatype.com/下载 HikariCP 的 JAR 包,在搜索框中输入 com.zaxxer:HikariCP,在结果里选择合适的版本,找到 Files 部分,下载 HikariCP-<version>.jar文件。
- 配置文件
在同级目录下创建 hikari.properties 配置文件,也可以在其他位置,只不过需要在使用的时候注意一下路径。
# 数据库连接信息
jdbcUrl=jdbc:mysql://localhost:3306/yourdatabase
username=yourusername
password=yourpassword
driverClassName=com.mysql.cj.jdbc.Driver
# 连接池配置
maximumPoolSize=10
minimumIdle=2
idleTimeout=30000
connectionTimeout=3000
- 代码加载配置文件实现
public class HikariCPConfigFileExample {
public static void main(String[] args) {
// 创建 Properties 对象用于加载配置文件
Properties properties = new Properties();
try {
// 加载配置文件
properties.load(new FileInputStream("src/main/resources/hikari.properties"));
// 创建 HikariConfig 对象,将配置文件内容传入
HikariConfig config = new HikariConfig(properties);
// 创建 HikariDataSource 对象,即连接池
HikariDataSource dataSource = new HikariDataSource(config);
// 从连接池获取连接
Connection connection = dataSource.getConnection();
} catch (IOException | SQLException e) {
e.printStackTrace();
} finally {
// 关闭数据源,释放资源
try {
if (connection != null) {
connection.close();
}
dataSource.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
- 常见的 HikariCP 连接池配置参数及说明
| 参数名 | 说明 | 示例 |
|---|---|---|
jdbcUrl | 数据库连接的 URL,指定数据库的地址、端口、数据库名等信息。 | jdbc:mysql://localhost:3306/mydb |
driverClassName | 数据库驱动的类名,HikariCP 通常可自动检测,但某些情况需手动指定。 | com.mysql.cj.jdbc.Driver |
username | 登录数据库的用户名。 | root |
password | 登录数据库的密码。 | 123456 |
minimumIdle | 连接池保持的最小空闲连接数,HikariCP 会尽力维持此数量的空闲连接。 | 5 |
maximumPoolSize | 连接池允许的最大连接数,达到该值后新的连接请求会被阻塞。 | 20 |
initializationFailTimeout | 连接池初始化时,若获取连接失败,在指定毫秒数内会重试。若超过此时间仍未成功,则初始化失败。 | -1 表示无限重试,正数为具体毫秒数 |
connectionTimeout | 客户端从连接池获取连接的最大等待时间(毫秒),超时则抛出异常。 | 30000(30 秒) |
idleTimeout | 连接在连接池中保持空闲状态的最大时间(毫秒),超过且连接数大于 minimumIdle 时会被关闭。 | 600000(10 分钟) |
maxLifetime | 连接在连接池中的最大存活时间(毫秒),超过则会被标记为过期并在下次使用时关闭。 | 1800000(30 分钟) |
connectionTestQuery | 用于验证连接有效性的 SQL 查询语句,在无法自动验证时使用。 | SELECT 1 |
validationTimeout | 验证连接有效性的最大等待时间(毫秒),超时则认为连接无效。 | 5000(5 秒) |
isAutoCommit | 是否自动提交事务,默认 true,即每条 SQL 语句执行后自动提交。 | true |
poolName | 连接池的名称,用于日志和监控,便于识别不同的连接池。 | MyHikariCP |
leakDetectionThreshold | 连接泄漏检测的阈值(毫秒),若连接占用时间超过此值,会记录日志并报告泄漏。 | 0 表示禁用检测 |
readOnly | 设置从连接池获取的连接是否为只读模式。 | false |
2.4 Druid 连接池
Druid 是阿里巴巴开源的数据库连接池,它结合了监控和防御 SQL 注入等功能,是一个功能强大且全面的连接池。
【优点】
- 监控功能强大:提供了丰富的监控功能,能够实时监控数据库连接的使用情况、SQL 执行情况等,方便进行性能调优和问题排查。
- 安全防护:具备防御 SQL 注入攻击的能力,提高了应用程序的安全性。
- 性能较好:在性能方面也有不错的表现,能满足大多数项目的需求。
【缺点】
- 资源占用稍多:相较于一些轻量级的连接池,Druid 占用的系统资源稍多。
适用于对数据库监控和安全有较高要求的项目,尤其是互联网项目。
如何使用
- 引入依赖jar包
下载地址:https://repo1.maven.org/maven2/com/alibaba/druid/ 根据需要的版本号导航到相应的目录下载jar包。下载完成后,将jar包引入到编辑器中,进行使用。
可以通过代码或者配置文件来配置 Druid 连接池,但是因为配置文件方式更加的灵活常用,所以这里就只说一下配置文件的实现方式。
- 配置文件
在同级目录下创建 druid.properties 配置文件,也可以在其他位置,只不过需要在使用的时候注意一下路径。
# 数据库连接信息
url=jdbc:mysql://10.10.20.235:3306/database
username=username
password=password
driverClassName=com.mysql.cj.jdbc.Driver
# 连接池配置
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-active=20
spring.datasource.druid.max-wait=60000
- 代码加载配置文件实现
public class DruidConfigFileExample {
public static void main(String[] args) {
try {
// 1. 加载外部配置文件
Properties properties = new Properties();
// /src下的文件,可以使用类加载器提供的方法
InputStream inputStream = DruidConfigFileExample.class.getClassLoader().getResourceAsStream("druid.properties");
properties.load(inputStream);
// 2. 使用连接池的工具类的工程模式,创建连接池
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
// 3. 获取数据库连接
Connection connection = dataSource.getConnection();
// 4. 关闭连接
connection.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭数据源
try {
if (connection != null) {
connection.close();
}
dataSource.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
- 常见的 Druid 连接池配置参数及说明
除了前面4个必要的数据连接配置参数,其他的参数都可以进行针对性选配。
| 参数名 | 说明 | 示例值 |
|---|---|---|
name | 连接池的名字,用于在监控和管理中标识连接池。 | druidDataSource |
url | 数据库连接的URL,指定要连接的数据库实例的地址和相关参数。 | jdbc:mysql://localhost:3306/mydb |
username | 登录数据库的用户名。 | root |
password | 登录数据库的密码。 | password123 |
driverClassName | 数据库驱动的类名,用于加载数据库驱动程序。 | com.mysql.cj.jdbc.Driver |
initialSize | 连接池初始化时创建的连接数量。 | 10 |
minIdle | 连接池中保持的最小空闲连接数。 | 5 |
maxActive | 连接池中允许的最大活动连接数。 | 20 |
maxWait | 获取连接时的最大等待时间,单位为毫秒。超过该时间将抛出异常。 | 60000 |
timeBetweenEvictionRunsMillis | 连接池进行空闲连接回收的时间间隔,单位为毫秒。 | 30000 |
minEvictableIdleTimeMillis | 连接在池中保持空闲而不被驱逐的最小时间,单位为毫秒。 | 180000 |
validationQuery | 用于验证连接是否有效的SQL查询语句。 | SELECT 1 |
testOnBorrow | 在从连接池获取连接时,是否测试连接的有效性。 | true |
testOnReturn | 在将连接归还到连接池时,是否测试连接的有效性。 | false |
testWhileIdle | 在连接空闲时,是否进行连接有效性测试。 | true |
poolPreparedStatements | 是否缓存PreparedStatement对象。 | true |
maxPoolPreparedStatementPerConnectionSize | 每个连接中缓存的最大PreparedStatement数量。 | 50 |
filters | 配置连接池的过滤器,用于监控、日志记录等功能。 | stat,log4j |
connectionProperties | 设置连接相关的属性,如字符集、时区等。 | characterEncoding=UTF-8;timezone=GMT+8 |
useGlobalDataSourceStat | 是否使用全局数据源统计信息。 | true |
2.5 对比总结
| 连接池产品 | 性能 | 功能丰富度 | 配置复杂度 | 适用场景 |
|---|---|---|---|---|
| DBCP | 一般,高并发场景欠佳 | 基本功能 | 简单 | 小型项目,对性能要求不高 |
| C3P0 | 一般 | 丰富,有高级特性 | 复杂 | 对连接管理功能要求高,性能要求一般的项目 |
| HikariCP | 卓越 | 较少配置选项 | 相对简单 | 高并发、追求高性能和低延迟的项目 |
| Druid | 较好 | 强大,有监控和安全防护 | 中等 | 对数据库监控和安全要求高的项目 |
综上所述,数据库连接池技术在提高数据库操作性能和资源利用率方面具有重要作用。DBCP 连接池和 C3P0 连接池等各有优缺点,适用于不同的项目场景。开发者在实际项目中,应根据项目的规模、并发量以及对连接管理功能的需求等因素,选择合适的连接池。同时,合理配置连接池的参数也是确保系统性能和稳定性的关键。希望本文能为开发者在使用 JDBC 连接池时提供有益的参考,帮助大家更好地进行数据库操作和系统开发。
更多推荐



所有评论(0)