使用 JDBC 进行数据访问 (Data Access with JDBC)
Spring 框架 JDBC 抽象所提供的价值或许最好通过下表中列出的动作序列来展示。该表显示了哪些动作由 Spring 负责,哪些动作是你的责任。
| 动作 | Spring | 你 |
|---|---|---|
| 定义连接参数 | X | |
| 打开连接 | X | |
| 指定 SQL 语句 | X | |
| 声明参数并提供参数值 | X | |
| 准备并运行语句 (Statement) | X | |
| 设置循环以遍历结果(如果有) | X | |
| 为每次迭代执行工作 | X | |
| 处理任何异常 | X | |
| 处理事务 | X | |
| 关闭连接、语句和结果集 | X |
Spring 框架负责处理所有那些可能使 JDBC 成为如此繁琐 API 的底层细节。
补充教学
1. 模板方法模式 (Template Method Pattern)
Spring JDBC 的核心设计思想是模板方法模式。 在传统的 JDBC 编程中,90% 的代码都是样板代码(Boilerplate Code):
java
// 传统 JDBC - 痛苦面具
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = dataSource.getConnection(); // 1. 获取连接
ps = conn.prepareStatement(sql); // 2. 预编译
ps.setString(1, "value"); // 3. 设置参数
rs = ps.executeQuery(); // 4. 执行
while (rs.next()) { // 5. 循环
// --- 只有这里是你的业务逻辑 ---
User user = new User();
user.setId(rs.getLong("id"));
// ---------------------------
}
} catch (SQLException e) {
// 6. 异常处理
} finally {
// 7. 及其痛苦的资源释放
if (rs != null) try { rs.close(); } catch (SQLException e) {}
if (ps != null) try { ps.close(); } catch (SQLException e) {}
if (conn != null) try { conn.close(); } catch (SQLException e) {}
}而在 Spring JdbcTemplate 中,Spring 把步骤 1, 2, 4, 5, 6, 7 全部封装在“模板”里,只留下步骤 3 和业务逻辑核心给你:
java
// Spring JdbcTemplate - 优雅
jdbcTemplate.query(sql, (rs, rowNum) -> {
// 只有这里是你的业务逻辑
User user = new User();
user.setId(rs.getLong("id"));
return user;
}, "value");2. 资源泄露的终结者
初级开发者写 JDBC 最容易犯的错误就是忘记关闭连接或关闭顺序错误,导致数据库连接池爆满(Connection Leak),最终拖垮整个系统。 Spring JDBC 通过 strict 的 try-finally 块确保每一步操作后资源都能被正确释放。只要你使用 JdbcTemplate,你就永远不需要担心连接泄露问题。