我会按照以下结构来讲解,确保你从基础到实践都能理解:

- 核心概念:什么是 JDBC?
- 连接数据库的步骤(通用流程)
- 实战示例:连接 MySQL 数据库
- 实战示例:连接 PostgreSQL 数据库
- 最佳实践:使用
try-with-resources - 最佳实践:使用连接池 (如 HikariCP)
核心概念:什么是 JDBC?
JDBC 是 Java 语言中用来规范客户端程序如何访问数据库的应用程序接口,它提供了查询和更新数据库中数据的方法。JDBC 是 Java 和数据库之间的桥梁。
JDBC 本身只是一套规范(接口),数据库厂商(如 Oracle, MySQL, PostgreSQL)需要实现这套规范,提供我们称之为 JDBC 驱动 的具体实现类,我们的 Java 程序就是通过加载这些驱动来连接特定数据库的。
连接数据库的通用步骤
无论你使用哪种 SQL 数据库,连接的步骤基本都遵循以下模式:
- 加载 JDBC 驱动:在早期版本中,需要显式地加载驱动类(
Class.forName(...)),在现代 JDBC (4.0+) 中,驱动会自动注册,这一步通常可以省略。 - 获取数据库连接:使用
DriverManager类的getConnection()方法,提供数据库的 URL、用户名和密码来创建一个Connection对象。 - 创建 Statement 对象:通过
Connection对象创建一个Statement或PreparedStatement对象,用于执行 SQL 语句。 - 执行 SQL 语句:使用
Statement对象的executeQuery()(用于查询) 或executeUpdate()(用于更新/插入/删除) 方法来执行 SQL。 - 处理结果集:如果执行的是查询语句,会返回一个
ResultSet对象,你需要遍历这个对象来获取查询结果。 - 关闭资源:在
finally块或使用try-with-resources语句中,按顺序关闭ResultSet、Statement和Connection,以释放数据库资源。
实战示例:连接 MySQL 数据库
这是最常见的情况之一,我们将使用 Maven 来管理项目依赖,因为它能自动下载 JDBC 驱动。

步骤 1:添加 MySQL JDBC 驱动依赖
在你的 pom.xml 文件中添加以下依赖:
<dependencies>
<!-- MySQL Connector/J 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version> <!-- 建议使用最新稳定版 -->
</dependency>
</dependencies>
步骤 2:编写 Java 连接代码
假设你的 MySQL 数据库信息如下:
- 主机:
localhost - 端口:
3306 - 数据库名:
test_db - 用户名:
root - 密码:
your_password
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class MySqlConnectionExample {
// 数据库连接信息
private static final String DB_URL = "jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC";
private static final String USER = "root";
private static final String PASS = "your_password";
public static void main(String[] args) {
// 1. 加载驱动 (JDBC 4.0+ 后可省略,但显式写出更清晰)
// try {
// Class.forName("com.mysql.cj.jdbc.Driver");
// } catch (ClassNotFoundException e) {
// e.printStackTrace();
// return;
// }
// Connection, Statement, ResultSet 都需要关闭,所以我们在外部定义
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 2. 获取数据库连接
System.out.println("正在连接到数据库...");
conn = DriverManager.getConnection(DB_URL, USER, PASS);
System.out.println("数据库连接成功!");
// 3. 创建 Statement 对象
stmt = conn.createStatement();
// 4. 执行 SQL 查询
String sql = "SELECT id, name, age FROM users";
rs = stmt.executeQuery(sql);
// 5. 处理结果集
System.out.println("ID\tName\tAge");
while (rs.next()) {
// 通过列名或列索引获取数据
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
// 输出数据
System.out.println(id + "\t" + name + "\t" + age);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 6. 关闭资源
// 关闭的顺序很重要:先关闭 ResultSet,再 Statement,Connection
try {
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (conn != null) conn.close();
System.out.println("数据库连接已关闭。");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
代码解释:
DB_URL: 数据库的统一资源定位符。jdbc:mysql://: 协议和子协议,表示使用 MySQL 的 JDBC 连接。localhost:3306: 主机和端口。/test_db: 数据库名。?useSSL=false: 禁用 SSL(本地开发时常用)。&serverTimezone=UTC: 设置服务器时区,避免警告。
DriverManager.getConnection(): 核心方法,用于建立连接。conn.createStatement(): 创建一个Statement对象,用于执行静态 SQL 语句。stmt.executeQuery(sql): 执行查询,返回一个ResultSet对象。rs.next(): 将光标从当前位置向下移动一行,并判断是否有下一行数据。rs.getXXX(): 从ResultSet中获取数据,XXX是数据类型(如String,Int,Date等)。
实战示例:连接 PostgreSQL 数据库
过程几乎完全相同,只需要更换驱动和 URL。

步骤 1:添加 PostgreSQL JDBC 驱动依赖
在 pom.xml 中添加:
<dependencies>
<!-- PostgreSQL JDBC 驱动 -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.6.0</version> <!-- 建议使用最新稳定版 -->
</dependency>
</dependencies>
步骤 2:编写 Java 连接代码
假设你的 PostgreSQL 数据库信息如下:
- 主机:
localhost - 端口:
5432 - 数据库名:
testdb - 用户名:
postgres - 密码:
your_password
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class PostgresConnectionExample {
private static final String DB_URL = "jdbc:postgresql://localhost:5432/testdb";
private static final String USER = "postgres";
private static final String PASS = "your_password";
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
System.out.println("正在连接到 PostgreSQL 数据库...");
// PostgreSQL 驱动加载方式
Class.forName("org.postgresql.Driver");
conn = DriverManager.getConnection(DB_URL, USER, PASS);
System.out.println("数据库连接成功!");
stmt = conn.createStatement();
String sql = "SELECT id, name, email FROM employees";
rs = stmt.executeQuery(sql);
System.out.println("ID\tName\tEmail");
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
System.out.println(id + "\t" + name + "\t" + email);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
try {
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (conn != null) conn.close();
System.out.println("数据库连接已关闭。");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
主要区别:
- 驱动类名:
org.postgresql.Driver - URL 格式:
jdbc:postgresql://... - PostgreSQL 驱动通常需要显式加载
Class.forName。
最佳实践:使用 try-with-resources
手动关闭资源(try-catch-finally)代码冗长且容易出错,从 Java 7 开始,推荐使用 try-with-resources 语句,它可以自动实现资源的关闭。
优点:
- 代码更简洁。
- 自动关闭:只要实现了
AutoCloseable接口(Connection,Statement,ResultSet都实现了),资源会在try块执行完毕后自动关闭,即使发生异常。 - 关闭顺序:会按照声明的相反顺序自动关闭。
重构后的代码(以 MySQL 为例):
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class ModernJdbcExample {
private static final String DB_URL = "jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC";
private static final String USER = "root";
private static final String PASS = "your_password";
public static void main(String[] args) {
// try-with-resources 会自动关闭 conn, stmt, rs
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT id, name, age FROM users")) {
System.out.println("数据库连接成功!");
System.out.println("ID\tName\tAge");
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println(id + "\t" + name + "\t" + age);
}
} catch (SQLException e) {
e.printStackTrace();
}
// conn, stmt, rs 都已经被自动关闭了
System.out.println("资源已自动释放。");
}
}
这个版本更健壮、更易于维护,是现代 Java 开发的标准做法。
最佳实践:使用连接池
每次执行数据库操作都创建和销毁连接是非常消耗性能的,在实际生产环境中,我们使用 数据库连接池 来管理连接。
连接池是一个预先创建好并维护一定数量数据库连接的容器,当需要连接时,从池中获取一个用完后,再归还给池,而不是销毁。
为什么使用连接池?
- 性能提升:避免了频繁创建和销毁连接的开销。
- 资源复用:连接被多个请求复用。
- 控制并发:可以限制最大连接数,防止数据库因过多连接而崩溃。
流行的连接池:
- HikariCP: 目前性能最好的连接池,被 Spring Boot 2.x+ 默认采用。
- Apache DBCP: 一个老牌的连接池实现。
- C3P0: 另一个广泛使用的连接池。
使用 HikariCP 的示例:
步骤 1:添加 HikariCP 依赖
<dependencies>
<!-- HikariCP 连接池 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version> <!-- 建议使用最新稳定版 -->
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
步骤 2:编写代码
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class HikariCPExample {
public static void main(String[] args) {
// 1. 配置 HikariCP
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC");
config.setUsername("root");
config.setPassword("your_password");
config.setDriverClassName("com.mysql.cj.jdbc.Driver");
// 连接池配置(可选)
config.setMaximumPoolSize(10); // 最大连接数
config.setMinimumIdle(5); // 最小空闲连接数
config.setConnectionTimeout(30000); // 连接超时时间 (毫秒)
// 2. 创建数据源
HikariDataSource dataSource = new HikariDataSource(config);
try (Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT id, name, age FROM users")) {
System.out.println("从连接池成功获取连接!");
System.out.println("ID\tName\tAge");
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println(id + "\t" + name + "\t" + age);
}
} catch (SQLException e) {
e.printStackTrace();
}
// 注意:通常应用程序生命周期内 dataSource 不会关闭
// dataSource.close(); // 在应用关闭时调用
}
}
| 场景 | 关键点 | 推荐做法 |
|---|---|---|
| 学习/简单脚本 | 代码简单,直接连接 | 使用 try-with-resources + DriverManager |
| 生产环境/应用 | 性能、稳定性、并发性 | 使用连接池 (如 HikariCP) + try-with-resources |
| ORM 框架 (如 MyBatis, Hibernate) | 框架封装了 JDBC | 通常由框架内部管理连接池,开发者无需直接操作 Connection |
希望这份详细的指南能帮助你掌握 Java 连接 SQL 数据库的核心知识!
