使用连接池是 Java 应用连接数据库的标准实践,它能极大地提升性能和稳定性,下面我将从 “为什么用”、“用什么” 到 “怎么用”,为你提供一个完整且详细的指南。

为什么需要使用连接池?(连接池的优势)
想象一下没有连接池的场景:
- 每次请求都创建新连接:当一个用户请求需要访问数据库时,程序就要向 MySQL 服务器发起一个连接请求,这个过程包括 TCP 三次握手、验证用户信息等,是比较耗时的。
- 用完就关闭:请求处理完毕后,连接被关闭,下一个用户请求再来时,又要重复一遍上述的耗时过程。
- 资源浪费:频繁地创建和销毁连接,会消耗大量的 CPU 和内存资源,并且会给数据库服务器带来巨大的压力。
连接池(Connection Pool) 就是为了解决这些问题而生的,它的工作模式就像一个“连接的停车场”:
- 初始化:在应用启动时,连接池会预先创建一定数量的数据库连接,并将它们放入“池”中待命。
- 获取连接:当你的 Java 代码需要一个数据库连接时,不是去创建一个新的,而是从连接池中“借”一个(获取一个),这个过程非常快。
- 使用连接:使用这个连接来执行 SQL 语句、查询数据等。
- 归还连接:操作完成后,你不需要关闭这个连接(
connection.close()),而是将它“还”给连接池,连接池会对其进行检查和重置,然后放回池中,供下一个请求使用。 - 销毁连接:当应用关闭时,连接池会统一关闭池中所有的连接。
核心优势:
- 性能提升:避免了频繁创建和销毁连接的开销,响应速度更快。
- 资源复用:连接得到了复用,减少了对数据库的压力。
- 控制并发:可以限制应用的最大连接数,防止因连接过多而导致数据库崩溃。
- 管理方便:可以监控连接的使用情况,如活动连接数、空闲连接数等。
主流的 Java 连接池技术
目前市面上最流行、性能最好的连接池主要有以下几个:

| 连接池 | 特点 | 官方推荐 |
|---|---|---|
| HikariCP | 性能极高,代码简洁,稳定可靠,是目前公认的最快的连接池。 | Spring Boot 2.x 及以上版本的默认连接池。 |
| Druid | 性能优秀,功能非常强大,除了连接池功能,还提供了强大的监控功能(如 SQL 监控、Web 监控面板)。 | 国产优秀开源项目,在国内使用非常广泛。 |
| DBCP2 | Apache 出品,稳定可靠,但性能相比 HikariCP 稍弱。 | 配合 Tomcat 等服务器使用较多。 |
推荐选择:
- 追求极致性能:首选 HikariCP。
- 需要强大的监控和管理功能:首选 Druid。
- 项目老旧或特定依赖:可能使用 DBCP2。
本指南将以 HikariCP(推荐首选)和 Druid(功能强大)为例进行讲解。
准备工作
在编写代码之前,请确保你已经:
-
安装了 MySQL 数据库,并有一个可用的数据库。
(图片来源网络,侵删) -
创建了数据库和用户,我们创建一个名为
test_db的数据库,并创建一个用户java_user,密码为password123。CREATE DATABASE test_db; CREATE USER 'java_user'@'localhost' IDENTIFIED BY 'password123'; GRANT ALL PRIVILEGES ON test_db.* TO 'java_user'@'localhost'; FLUSH PRIVILEGES;
-
添加 JDBC 驱动依赖,你需要将 MySQL 的 JDBC 驱动(
mysql-connector-j)的 jar 包添加到你的项目中。Maven (
pom.xml)<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>8.0.33</version> <!-- 建议使用较新版本 --> </dependency>Gradle (
build.gradle)implementation 'com.mysql:mysql-connector-j:8.0.33'
实现步骤(以 HikariCP 为例)
HikariCP 的配置非常简单,主要通过一个 Properties 对象来完成。
步骤 1:创建 HikariConfig 对象并配置参数
这是连接池的核心配置,你需要提供数据库连接的基本信息。
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class HikariCPExample {
public static void main(String[] args) {
// 1. 创建 HikariConfig 配置对象
HikariConfig config = new HikariConfig();
// 2. 配置数据库连接信息 (非常重要)
// JDBC URL 格式: jdbc:mysql://[主机名]:[端口]/[数据库名]?[参数]
config.setJdbcUrl("jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC");
config.setUsername("java_user");
config.setPassword("password123");
// 3. (可选但推荐) 配置连接池参数
config.setDriverClassName("com.mysql.cj.jdbc.Driver"); // 对于新版本驱动,可以不设置,HikariCP会自动检测
config.setPoolName("MyHikariPool"); // 连接池名称
// 连接池中维护的最小空闲连接数
config.setMinimumIdle(5);
// 连接池中最大连接数
config.setMaximumPoolSize(15);
// 一个连接在池中最大空闲时间,超时后将被回收 (单位:毫秒)
config.setIdleTimeout(30000);
// 一个连接的生命周期,超时后将被强制关闭 (单位:毫秒)
config.setMaxLifetime(1800000); // 30 minutes
// 从连接池获取连接的最大等待时间,超时将抛出异常 (单位:毫秒)
config.setConnectionTimeout(20000);
// 4. 创建 HikariDataSource 数据源对象
HikariDataSource dataSource = new HikariDataSource(config);
// 5. 使用数据源获取连接,并进行数据库操作
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT 'Hello, HikariCP!' AS message")) {
if (resultSet.next()) {
String message = resultSet.getString("message");
System.out.println("数据库查询结果: " + message);
}
System.out.println("成功获取连接并执行查询!");
} catch (Exception e) {
e.printStackTrace();
}
// 6. (可选) 在应用关闭时关闭数据源
// dataSource.close();
}
}
关键配置说明:
jdbcUrl: 最核心的配置,必须正确,注意时区参数serverTimezone=UTC。username,password: 数据库的用户名和密码。maximumPoolSize: 非常关键,设置过小可能导致请求排队,设置过大会占用过多数据库资源,建议根据数据库服务器的承载能力和应用的并发量来设定。connectionTimeout: 当所有连接都在使用中时,新的请求需要等待多久,建议设置一个合理的超时时间(如 20-30 秒),避免无限等待。
步骤 2:如何管理 DataSource(最佳实践)
上面的例子中,每次操作都创建一个新的 DataSource 是非常低效的,在实际项目中,DataSource 应该是全局唯一的,通常通过单例模式或依赖注入(如 Spring 的 @Bean)来管理。
下面是一个使用单例模式管理 DataSource 的示例:
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.SQLException;
// 单例模式 DataSource 管理器
public class DataSourceManager {
// volatile 关键字确保多线程环境下 instance 的可见性
private static volatile DataSourceManager instance;
private HikariDataSource dataSource;
// 私有构造器
private DataSourceManager() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC");
config.setUsername("java_user");
config.setPassword("password123");
config.setMaximumPoolSize(10);
this.dataSource = new HikariDataSource(config);
}
// 提供全局访问点
public static DataSourceManager getInstance() {
if (instance == null) {
synchronized (DataSourceManager.class) {
if (instance == null) {
instance = new DataSourceManager();
}
}
}
return instance;
}
// 获取连接
public Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
// 关闭数据源 (通常在应用关闭时调用)
public void close() {
if (dataSource != null && !dataSource.isClosed()) {
dataSource.close();
}
}
}
使用方式:
public class Application {
public static void main(String[] args) {
DataSourceManager manager = DataSourceManager.getInstance();
try (Connection conn = manager.getConnection()) {
// 使用 conn 进行数据库操作...
System.out.println("从单例数据源获取连接成功!");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Druid 连接池示例
Druid 的使用方式与 HikariCP 类似,但配置项更多,并且自带监控功能。
步骤 1:添加 Druid 依赖
Maven (pom.xml)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.18</version> <!-- 建议使用较新版本 -->
</dependency>
步骤 2:编写代码
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
public class DruidExample {
public static void main(String[] args) {
// 方式一:硬编码配置 (不推荐)
/*
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC");
dataSource.setUsername("java_user");
dataSource.setPassword("password123");
dataSource.setInitialSize(5);
dataSource.setMaxActive(20);
*/
// 方式二:使用配置文件 (推荐)
// 在 resources 目录下创建 druid-config.properties
Properties props = new Properties();
try (InputStream is = DruidExample.class.getClassLoader().getResourceAsStream("druid-config.properties")) {
if (is == null) {
throw new RuntimeException("找不到 druid-config.properties 文件");
}
props.load(is);
// 1. 通过工厂类创建数据源
DataSource dataSource = DruidDataSourceFactory.createDataSource(props);
// 2. 获取连接
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT 'Hello, Druid!' AS message")) {
if (resultSet.next()) {
String message = resultSet.getString("message");
System.out.println("数据库查询结果: " + message);
}
System.out.println("成功从 Druid 连接池获取连接!");
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
src/main/resources/druid-config.properties 文件内容:
# 基本配置 url=jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC username=java_user password=password123 driverClassName=com.mysql.cj.jdbc.Driver # 连接池配置 initialSize=5 minIdle=5 maxActive=20 maxWait=60000 timeBetweenEvictionRunsMillis=60000 minEvictableIdleTimeMillis=300000 validationQuery=SELECT 1 testWhileIdle=true testOnBorrow=false testOnReturn=false poolPreparedStatements=true maxPoolPreparedStatementPerConnectionSize=20
Druid 的最大亮点是它的监控,你可以通过配置开启 Web 监控页面,非常方便地查看 SQL 执行情况、连接池状态等。
在 Spring Boot 中集成(最简单的方式)
在现代 Java 开发中,我们大多使用 Spring Boot,它极大地简化了连接池的配置。
添加 spring-boot-starter-data-jpa 依赖
它会自动引入 HikariCP 和 JDBC 驱动。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
在 application.properties 或 application.yml 中配置
application.properties
# DataSource Configuration spring.datasource.url=jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC spring.datasource.username=java_user spring.datasource.password=password123 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # HikariCP Specific Configuration (可选,使用默认值即可) spring.datasource.hikari.connection-timeout=30000 spring.datasource.hikari.maximum-pool-size=10 spring.datasource.hikari.minimum-idle=5 spring.datasource.hikari.idle-timeout=600000
application.yml (更推荐)
spring:
datasource:
url: jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC
username: java_user
password: password123
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
connection-timeout: 30000
maximum-pool-size: 10
minimum-idle: 5
idle-timeout: 600000
创建实体类和 Repository
// User.java (实体类)
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// getters and setters...
}
// UserRepository.java (数据访问层)
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
在 Service 中使用
Spring Boot 会自动配置好一个名为 dataSource 的 Bean,你只需要通过 @Autowired 注入 JpaRepository 即可,Spring Data JPA 会在内部自动处理连接的获取和释放。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public void addUser(String name) {
User user = new User();
user.setName(name);
userRepository.save(user);
System.out.println("用户添加成功!");
}
}
Spring Boot 的自动配置功能让你几乎不需要写任何连接池相关的 Java 代码,非常方便。
| 方面 | 说明 |
|---|---|
| 核心概念 | 连接池通过复用预创建的数据库连接,避免了频繁创建/销毁的开销,从而提升性能、节省资源、控制并发。 |
| 技术选型 | HikariCP (性能之王,Spring Boot 默认)、Druid (功能强大,带监控)。 |
| 手动集成 | 添加 JDBC 驱动和连接池依赖。 创建连接池配置对象 ( HikariConfig / DruidDataSource)。配置数据库连接信息 ( url, user, pass) 和连接池参数 (maxPoolSize 等)。创建数据源 ( DataSource) 对象。关键:通过单例等方式全局管理 DataSource。从 DataSource 获取 Connection 进行操作。 |
| Spring Boot 集成 | 极其简单。 添加 spring-boot-starter-data-jpa 依赖。在 application.yml 中配置数据源参数即可,Spring Boot 会自动配置好 HikariCP。 |
| 最佳实践 | 始终使用连接池,而不是每次都创建新连接,在 Spring Boot 项目中,直接使用其自动配置功能,在传统项目中,使用 HikariCP 并通过单例模式管理 DataSource。 |
