Java JDBC 编程:连接数据库并完成基本查询

数据库几乎是后端开发的核心组成部分,而 JDBC 是 Java 访问关系型数据库的基础方式。即使以后会用到 MyBatis、Hibernate 等框架,理解 JDBC 仍然非常重要,因为很多数据库交互本质上都建立在它之上。

对初学者来说,JDBC 既是一个知识点,也是理解“程序如何和数据库沟通”的最好入口。只要 JDBC 的基本链路理解透了,后面再学任何数据访问框架,都不会只停留在“会配置、会调用”的表面。

一、JDBC 的位置是什么

JDBC 可以理解为 Java 访问数据库的标准接口规范。不同数据库厂商会提供自己的驱动,而 Java 程序则通过统一 API 去建立连接、执行 SQL、读取结果。

也正因为有这层统一标准,很多上层框架才能在不同数据库之间保持相对一致的使用方式。换句话说,JDBC 是 Java 数据库编程世界里的“共同语言”。

二、一次数据库操作通常要经历什么步骤

最基本的流程通常包括:

  1. 获取连接;
  2. 创建语句对象;
  3. 执行 SQL;
  4. 读取结果集;
  5. 关闭资源。

看起来步骤固定,但每一步背后其实都对应着真实的数据库交互过程。只要你能把这条链路理解透,后面再学 ORM 或数据库框架时,就不会只停留在“会配置、会调用”的层面。

三、JDBC 背后的通信原理可以怎么理解

从本质上说,JDBC 做的是“Java 程序通过驱动和数据库服务器通信”。

大致可以把它理解为这样一条链路:

  • Java 代码调用 JDBC API;
  • JDBC 驱动把这些调用翻译成数据库能理解的协议交互;
  • 数据库执行 SQL;
  • 驱动再把结果转换成 Java 可以读取的 ResultSet 等对象。

也就是说,驱动并不是一个“可有可无的 jar 包”,而是 Java 与具体数据库之间的适配桥梁。没有驱动,JDBC 规范本身并不会自动知道该如何和 MySQL、PostgreSQL 或 Oracle 通信。

四、Connection、Statement、PreparedStatement、ResultSet 分别是什么

1. Connection

Connection 表示一个数据库连接。你可以把它理解为 Java 程序和数据库之间建立起来的一条会话通道。

它不仅用于执行 SQL,还和事务控制密切相关,例如提交、回滚、设置自动提交等。

2. Statement

Statement 可以直接执行普通 SQL 字符串,适合简单场景,但不适合频繁传参的业务代码。

3. PreparedStatement

PreparedStatement 是更常用、也更推荐的方式。它支持预编译 SQL 模板,并通过占位符设置参数。这不仅更清晰,也能减少 SQL 注入风险。

4. ResultSet

ResultSet 表示查询结果集。你可以把它理解为数据库返回数据的一层游标视图,程序通过不断调用 next() 向后读取每一行。

理解这几个对象的职责分工后,JDBC 代码就不再是一串看起来啰嗦的模板,而是一条明确的数据访问链路。

五、一个基础的 JDBC 查询示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.sql.*;

public class Main {
public static void main(String[] args) throws Exception {
String url = "jdbc:mysql://localhost:3306/test";
try (Connection conn = DriverManager.getConnection(url, "root", "123456");
PreparedStatement ps = conn.prepareStatement("select id, name from user where id=?")) {
ps.setInt(1, 1);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("name"));
}
}
}
}

这段代码把 JDBC 最核心的几个步骤都串了起来:建立连接、预编译 SQL、传入参数、执行查询、读取结果。理解它,比死记任何框架注解都更有基础价值。

在真实项目中,这段代码背后对应的就是一次完整的数据访问请求:应用拿到连接,向数据库发送 SQL,把结果转成 Java 对象,再交给业务层继续处理。

六、为什么 PreparedStatement 比 Statement 更值得优先使用

很多初学者一开始会觉得 PreparedStatement 只是写法更复杂一点,但实际上它有两个非常重要的价值:

1. 更安全

如果直接字符串拼接 SQL,用户输入很容易破坏原有 SQL 结构,形成 SQL 注入风险。

2. 更适合参数化查询

真实业务里大量 SQL 都只是参数不同、结构相同。预编译语句更适合这种模式,也让代码更清晰。

所以在现代 Java 开发里,只要涉及用户输入和动态参数,优先考虑 PreparedStatement 基本是默认共识。

七、为什么事务一定要理解

只要一次业务操作涉及多条 SQL,就可能需要事务来保证一致性。最典型的例子就是转账:

  • A 账户扣钱;
  • B 账户加钱。

如果只执行成功一半,数据就会错。事务的核心价值,就是让这组操作要么全部成功,要么全部失败。

在 JDBC 里,事务通常和 Connection 绑定。你需要理解几个基本点:

  • 自动提交模式下,每条 SQL 可能会立刻提交;
  • 关闭自动提交后,可以手动控制 commitrollback
  • 事务不是“框架专属概念”,底层 JDBC 就已经在参与它。

很多人学到框架后才接触事务,结果总觉得抽象。其实如果你先把 JDBC 里的事务概念理解好,再去看声明式事务,会顺畅很多。

八、为什么连接池一定要理解

数据库连接不是“随手 new 一个对象”这么简单。建立连接通常要经过网络交互、认证、资源分配等过程,成本不低。

如果每来一个请求就现建连接、用完就销毁,在高并发场景下性能会很差,数据库也承受不了。因此真实项目里一般都会使用连接池。

连接池的核心价值包括:

  • 复用已有连接,减少连接创建成本;
  • 控制最大连接数,避免数据库被打爆;
  • 提供连接生命周期管理;
  • 统一做超时、校验和回收。

所以从工程角度看,JDBC 的重点不只是“怎么连上数据库”,还包括“怎么高效、稳定地管理连接”。

九、JDBC 使用中的常见注意事项

1. 资源释放一定要重视

连接、语句对象、结果集都属于需要及时释放的资源。忘记关闭,轻则造成内存和连接泄漏,重则把数据库连接池耗尽。

这也是为什么 try-with-resources 写法非常值得养成习惯。

2. 不要拼接 SQL

直接字符串拼接很容易埋下 SQL 注入风险,也会让代码可读性和可维护性变差。

3. 不要只关注“能查出来”

数据库访问不只是写出一条能跑的 SQL,还要关心:

  • 参数是否安全;
  • 结果是否正确映射;
  • 事务是否完整;
  • 资源是否释放;
  • 性能是否可接受。
4. 结果集读取要有字段意识

读取数据时,字段名、列顺序、数据类型都要对应准确。很多问题并不是 JDBC API 本身难,而是 SQL 和 Java 模型之间映射不清晰。

十、学习建议

  1. 先亲手跑通一次最简单的查询,再学更高级的数据访问框架。
  2. 把 SQL、连接、结果集和事务看成一条完整链路来理解。
  3. 遇到数据库问题时,先回到底层 JDBC 模型思考。
  4. 学框架时,反复问自己:底层 JDBC 到底做了什么封装。

总结

JDBC 是理解 Java 数据库访问的基础。哪怕后面主要使用 ORM 或数据访问框架,只要把 JDBC 的连接、SQL 执行、结果集、事务和连接池理解透彻,很多数据库问题都会更容易排查。

真正值得掌握的,不只是模板代码,而是这几层认知:

  • JDBC 是统一规范,驱动负责连接 Java 和具体数据库;
  • 一次数据库访问本质上是连接、执行、读取、释放资源的完整链路;
  • PreparedStatement 在安全性和工程实践上更值得优先使用;
  • 事务决定数据一致性,连接池决定系统稳定性和性能。

把这些底层逻辑想明白之后,再去看 MyBatis、Hibernate、Spring JDBC,你会更容易理解它们到底替你省掉了哪些重复劳动,又隐藏了哪些需要自己继续掌握的底层细节。

参考资源