说说 JDBC 的执行步骤?
2026年01月08日
一则或许对你有用的小广告
欢迎 加入小哈的星球 ,你将获得: 专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新开坑项目: 《Spring AI 项目实战(问答机器人、RAG 增强检索、联网搜索)》 正在持续爆肝中,基于
Spring AI + Spring Boot3.x + JDK 21..., 点击查看; - 《从零手撸:仿小红书(微服务架构)》 已完结,基于
Spring Cloud Alibaba + Spring Boot3.x + JDK 17..., 点击查看项目介绍; 演示链接: http://116.62.199.48:7070/; - 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/
面试考察点
面试官提出这个问题,通常旨在考察以下几个层面:
- 基础知识掌握:你是否能准确、完整地背出 JDBC 的标准执行流程。
- 对关键组件作用的理解:面试官不仅仅是想知道你记住了步骤,更是想知道你是否理解每个核心对象(如
DriverManager、Connection、Statement、ResultSet)的职责和生命周期。 - 资源管理与安全意识:你是否具备在代码中妥善管理数据库连接、语句、结果集等稀缺资源的意识,能否清晰地阐述
try-with-resources或finally块的重要性,以及是否了解使用PreparedStatement来防止 SQL 注入。 - 实践与原理结合:能否将步骤与 JDBC 作为 “Java 数据库连接” 抽象层的设计思想联系起来,理解其“驱动”机制和标准接口的意义。
核心答案
标准的 JDBC 执行步骤如下,共七步:
- 加载并注册数据库驱动:通常使用
Class.forName()加载驱动类,现代 JDBC 驱动可自动注册。 - 建立数据库连接:通过
DriverManager.getConnection(url, user, password)获取Connection对象。 - 创建 Statement 对象:通过
Connection对象创建Statement、PreparedStatement或CallableStatement。 - 执行 SQL 语句:使用创建的 Statement 对象执行查询(
executeQuery)或更新(executeUpdate)。 - 处理结果集:如果是查询操作,遍历
ResultSet对象获取数据。 - 关闭结果集和 Statement 对象:显式关闭以释放数据库资源。
- 关闭数据库连接:将
Connection返回给连接池或直接关闭。
深度解析
原理/机制
JDBC(Java Database Connectivity)是 Java 定义的一套独立于数据库的统一 API。它的核心在于 “驱动” 机制:各大数据库厂商提供实现了 java.sql.Driver 接口的 Jar 包(驱动)。我们的程序通过 JDBC API 与 DriverManager 交互,由 DriverManager 委托给具体的驱动实现去操作数据库。这使得我们的应用代码与具体数据库解耦。
代码示例与步骤详解
以下是一个使用 PreparedStatement(推荐方式)执行查询的完整示例,并附有详细注释。
// 1. 加载驱动 (JDBC 4.0+ 后,驱动 Jar 包中的 META-INF/services/java.sql.Driver 文件
// 会被自动加载,此步骤常可省略,但显式写出更清晰)
Class.forName(“com.mysql.cj.jdbc.Driver”);
// 2. 建立连接 (生产环境通常从连接池获取,而非直接 DriverManager)
String url = “jdbc:mysql://localhost:3306/test_db?serverTimezone=UTC&characterEncoding=utf8”;
String user = “root”;
String password = “123456”;
// 关键:使用 try-with-resources 确保 Connection, Statement, ResultSet 被自动关闭
try (Connection conn = DriverManager.getConnection(url, user, password);
// 3. 创建 PreparedStatement 对象 (预编译,防SQL注入,性能更优)
PreparedStatement pstmt = conn.prepareStatement(“SELECT id, name FROM users WHERE age > ?”)) {
// 4. 设置参数并执行 SQL
pstmt.setInt(1, 18); // 将第一个占位符 `?` 替换为 18
try (ResultSet rs = pstmt.executeQuery()) { // 嵌套 try-with-resources 管理 ResultSet
// 5. 处理结果集
while (rs.next()) {
int id = rs.getInt(“id”); // 通过列名获取
String name = rs.getString(“name”);
System.out.println(“ID: “ + id + “, Name: “ + name);
}
} // 6. 自动关闭 ResultSet
} // 7. 自动关闭 PreparedStatement 和 Connection
catch (ClassNotFoundException e) {
System.err.println(“未找到数据库驱动类!”);
e.printStackTrace();
} catch (SQLException e) {
System.err.println(“数据库操作异常!”);
e.printStackTrace();
}
对比分析:Statement vs PreparedStatement
- Statement:用于执行静态 SQL 语句。存在 SQL 注入风险,且每次执行都需要数据库进行编译。
- PreparedStatement:
- 预编译:SQL 模板被预先编译并缓存,多次执行(参数不同)时效率更高。
- 防止 SQL 注入:参数通过
setXxx()方法传入,驱动程序会进行正确的转义,从根本上杜绝了拼接字符串导致的安全漏洞。 - 结论:绝大多数场景下都应使用
PreparedStatement。
最佳实践与常见误区
- 最佳实践:
- 使用连接池:如 HikariCP、Druid。直接通过
DriverManager获取连接是昂贵的操作,连接池能显著提升性能。 - 始终使用
PreparedStatement:避免 SQL 注入,提升性能。 - 使用 Try-With-Resources(Java 7+):确保
Connection、Statement、ResultSet这些实现了AutoCloseable接口的资源被自动、正确地关闭,即使在发生异常时也是如此。这比在finally块中手动关闭更简洁、安全。 - 正确关闭资源:关闭顺序应为:
ResultSet->Statement->Connection(在 try-with-resources 中顺序声明即可,它会逆序关闭)。
- 使用连接池:如 HikariCP、Druid。直接通过
- 常见误区:
- 忘记关闭资源或关闭顺序错误:导致数据库连接耗尽(Connection Leak)。
- 在循环内部创建连接或 Statement:应在外层创建,循环内仅设置参数和执行。
- 混用
ResultSet的getXxx(列索引)和getXxx(列名):建议统一使用列名,提高代码可读性和健壮性。 - 忽略事务控制:默认
autoCommit=true,每条 SQL 独立事务。对于需要原子性的操作,应使用conn.setAutoCommit(false),并在成功后conn.commit(),异常时conn.rollback()。
总结
JDBC 的核心执行步骤是 “加载驱动、建立连接、创建语句、执行 SQL、处理结果、关闭资源”;理解这一流程的关键在于把握各核心对象的作用与生命周期,并在实践中强制使用 PreparedStatement 和 Try-With-Resources 来保障安全性与资源管理。