JDBC是Java官方定义的数据库连接接口规范,不是具体jar包;核心组件包括DriverManager(驱动匹配)、Connection(真实连接实例)、Statement/PreparedStatement(SQL执行),问题定位需分层:规范层、驱动实现层、资源管理层。

Java JDBC 百问百答不是要背下所有问题,而是抓住三根主线:规范定位、核心组件职责、真实问题归因。回答时别堆概念,直接对应“你在哪一层出的问题”,就能把答案讲清楚、用得上。
JDBC 是什么?不是 jar 包,是接口规范
它不是某个具体工具或库,而是 Java 官方定义的一套标准接口(在 java.sql 和 javax.sql 包里)。你写的代码只依赖这些接口,不依赖 MySQL 或 Oracle 的实现细节。
- mysql-connector-j、ojdbc8 这些是厂商提供的驱动实现,它们实现了 JDBC 接口
- JDK 自带 DriverManager、Connection、Statement 等类/接口,但不包含任何数据库逻辑
- 所以“引入 mysql-connector-j 就能用 JDBC”这句话对一半——真正起作用的是驱动对 JDBC 规范的实现
getConnection() 到底发生了什么?
调用 DriverManager.getConnection(url, user, pwd) 不是简单发个 TCP 请求,而是一次“匹配 + 初始化”过程:
- JVM 启动时或首次调用前,会扫描 classpath 下所有 META-INF/services/java.sql.Driver 文件(JDBC 4.0+ 自动发现机制)
- 每个文件里写明了驱动类全名(如 com.mysql.cj.jdbc.Driver),JDBC 加载并实例化它
- DriverManager 拿着你传入的 URL(如 jdbc:mysql://localhost:3306/test)去比对各驱动的 acceptsURL() 方法,选中匹配的那个
- 最终由该驱动创建并返回一个真实的 Connection 实例(比如 MySQLConnection)
为什么线上连接池打满?关键不在 ORM,在 Connection 生命周期
很多同学查日志看到 “MyBatis 执行 SQL 很慢”,就去优化 SQL,结果没用——问题常卡在 JDBC 层的资源管理上:
立即学习“Java免费学习笔记(深入)”;
- Connection 泄漏:没在 finally 或 try-with-resources 里 close(),连接一直占着不放
- 事务未提交/回滚:Connection 被拿去执行 update,但没 commit 或 rollback,后续请求等锁
- 超时设置不合理:socketTimeout=0(永不超时)或太长,网络抖动时连接卡死
- 连接池配置失衡:maxPoolSize 设太高,DB 扛不住;设太低,应用排队等连接
PreparedStatement 为什么比 Statement 安全又快?
不只是防 SQL 注入,本质是复用执行计划:
- Statement 每次都把完整 SQL 发给数据库,DB 需重新解析、生成执行计划
- PreparedStatement 首次执行时编译一次,后续只传参数值,DB 直接复用计划(尤其适合循环插入/批量查询)
- 参数自动转义,避免拼接字符串带来的注入风险(比如 username = "admin' -- ")
- 注意:? 占位符不能用于表名、列名、排序字段等动态结构,那些仍需服务端校验后白名单拼接
不复杂但容易忽略。


















