Java与MySQL协同需打通连接层→SQL层→优化层→应用层四关,核心爆雷点在于SQL性能瓶颈、索引失效、Connection/ResultSet泄漏、时区错配及事务不一致,而非语法错误。

Java 与 MySQL 的协同不是“配个驱动就能跑”,而是要打通连接层→SQL层→优化层→应用层四道关卡。真正卡住多数人的,从来不是语法写不对,而是不知道哪条 SQL 在拖慢接口、为什么加了索引却没生效、JDBC 中 ResultSet 没关导致连接池耗尽——这些才是实战中高频爆雷点。
搞懂 JDBC 连接背后的三件事
别只记 DriverManager.getConnection();重点看三个隐性行为:
- 连接不是“一建永逸”:MySQL 默认 wait_timeout=28800(8小时),但很多连接池(如 HikariCP)会主动探测空闲连接,超时前就回收。若代码里手动 new Connection 却不 close,迟早 Connection leak;
-
时区必须显式声明:JDBC URL 不加
?serverTimezone=Asia/Shanghai,Java 的 LocalDateTime 写入数据库可能偏移 14 小时——尤其 SpringBoot 2.3+ 默认禁用 legacy timezone fallback; - useSSL=false 不是偷懒,是必要配置:本地开发或内网部署时,MySQL 8.0+ 默认要求 SSL,不加该参数会报 “Public Key Retrieval is not allowed”,加了才走明文握手流程。
SQL 写对 ≠ 查询快:盯死执行计划
在 Java 里执行一条 SELECT,光看代码看不出性能瓶颈。必须进 MySQL 执行 EXPLAIN + 你的 SQL:
- 看到
type=ALL→ 全表扫描,立刻检查 WHERE 字段有没有索引; - 看到
Extra: Using filesort→ 排序没走索引,要么补联合索引(注意最左前缀),要么加ORDER BY ... LIMIT N控制排序数据量; - 看到
rows值远大于实际返回行数 → 索引选择性差,比如对性别字段建索引,区分度低,优化器宁愿全扫也不走。
Java 层最容易忽略的三个细节
这些不报错,但会在高并发下突然崩:
立即学习“Java免费学习笔记(深入)”;
-
PreparedStatement 预编译不是可选项:拼接字符串执行 SQL(
"SELECT * FROM user WHERE id = " + userId)既危险又低效——每次执行都触发 SQL 解析、生成执行计划;PreparedStatement 复用计划,还天然防注入; - ResultSet 必须在 finally 或 try-with-resources 里 close:它背后绑着 socket 和内存缓冲区,不关会导致连接无法释放、OOM;Spring JDBC 和 MyBatis 已帮你封装,但手写 JDBC 时务必手动关;
-
事务边界别交给 @Transactional “自动猜”:比如一个 service 方法里先查再 insert 再 update,若没明确 propagation 和 isolation,异常时可能部分提交、部分回滚,数据不一致。建议显式标注
@Transactional(rollbackFor = Exception.class)。
从建表开始就为 Java 服务
Java 开发者建表时,别只想着“能存进去就行”:
- 主键用
BIGINT UNSIGNED AUTO_INCREMENT而非 INT —— 避免未来 ID 溢出,MyBatis-Plus 的雪花 ID 也默认 long 类型; - 时间字段统一用
DATETIME(非 TIMESTAMP),并设DEFAULT CURRENT_TIMESTAMP—— Java 侧用 LocalDateTime 直接映射,无时区转换烦恼; - 字符串字段按需选
VARCHAR(255)或TEXT,别全用 TEXT —— InnoDB 对 VARCHAR 存储更紧凑,且支持前缀索引;大文本才上 TEXT。


















