很多初学者学 Java 数据库编程,第一步就是拿 JDBC 连 MySQL,但真正动手时会发现坑一个接一个——驱动类加载报错、连接超时、中文乱码、时区问题,甚至好不容易连上了,增删改查又不知道该从哪里下手。这篇内容就是用最直接的方式,把 Java 连接 MySQL 并完成数据交互的完整链路拆开讲透。里面包含我实际反复用过的连接代码、踩过的坑、以及一套可以直接拿去改的连接工具类,不管是准备课程设计、做期末项目,还是想搞懂 JDBC 底层原理,都值得收藏一份。
1. 整体设计与思路拆解
1.1 为什么第一课必须从 JDBC 开始
很多人问我,现在开发都用 MyBatis、Spring Data JPA,为什么还要学原生的 JDBC?我的看法很明确:框架只是 JDBC 的封装,底层再怎么花哨,最终还是走的 java.sql 包里的那套接口。学习 JDBC 不是为了让你以后写项目都手写连接,而是让你在遇到问题的时候,能顺着调用链往下追,而不是对着报错信息干瞪眼。
举个例子。你用 MyBatis 执行一条 insert,突然报了一个事务相关的错误。如果你不知道 MyBatis 底层拿到的其实就是 Connection,不知道它背后调用了 setAutoCommit(false) 和 commit(),你根本不知道去哪里查问题。我见过不少工作了两年的人,让他解释 MyBatis 的 SqlSession 跟 JDBC 的 Connection 之间的关系,依然一脸懵。这就是没打好底子的典型表现。
另外,JDBC 这套流程非常固定,一共就六步:加载驱动、获取连接、创建 Statement、执行 SQL、处理结果集、释放资源。只要你把这六步吃透,后面学什么数据库中间件都很快,因为所有的工具都是在替你简化这六步中的某几步。所以我的建议是:第一课必须手写一遍 JDBC,哪怕你已经会用 MyBatis,也值得从头走一遍,把每个环节的细节搞清楚。
1.2 JDBC 直连与 ORM 框架的取舍
既然题目是“数据交互”,就绕不开一个话题:到底是直接用 JDBC,还是上 ORM 框架?我给不同阶段的读者一个比较务实的结论:
- 如果你的目标是快速完成一个课程设计或者小工具,对并发和工程化要求不高,直接用 JDBC 完全够用,甚至代码量更少。
- 如果你是在做企业项目,需要处理复杂查询、分页、多表关联,直接用 JDBC 会写吐,这时上 MyBatis 或 JPA 更合理。
- 但无论哪种情况,你都应该知道 JDBC 写法的基本范式,因为框架的 bug 报错底层往往指向 JDBC 层,不懂底层排查成本极高。
从工程角度对比一下:
| 对比维度 | JDBC 原生 | ORM 框架(MyBatis 为例) |
|---|---|---|
| 学习成本 | 低,核心概念就几个 | 高,需要理解代理、映射、生命周期 |
| SQL 控制力 | 完全手动,灵活 | SQL 写在 XML 中,可控性也不错 |
| 开发效率 | 低,重复代码多 | 高,大量模板代码被自动处理 |
| 调试难度 | 出问题好定位 | 有一层封装,需要追源码 |
| 连接管理 | 自己管 | 框架集成连接池自动管 |
你会发现,JDBC 的唯一劣势是“重复代码多”,但这不是 JDBC 本身的问题,而是缺少封装。实际上你只要写一个 DBUtil 连接工具类和一个统一的 BaseDao,重复代码就能压到很低。这篇博客后面给到的示例,就采用了这种“原生 JDBC + 轻量封装”的方式,一方面是贴近课程设计的需求,另一方面也能让读者看清每一步在做什么。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与核心参数解析
2.1 版本选型:JDK、MySQL、驱动的三角关系
我遇到过太多版本不匹配导致的诡异报错,所以先把版本问题放在最前面。当前时间点写这篇文章,我的推荐组合是:
- JDK 8 或 11。JDK 8 是兼容性最好的版本,绝大多数的教材和企业老项目都在用;JDK 11 属于 LTS 版本,想用新版语法可以用它。
- MySQL 5.7 或 8.0。如果你是想体验 MySQL 8 的新特性,直接装 8.0;如果你想减少认证、字符集方面的麻烦,5.7 是老牌稳定选择。不过新项目我建议直接 8.0,别再用老版本了。
- MySQL Connector/J 驱动版本。这个最关键,8.0.x 的驱动和 5.1.x 的驱动写法完全不同。
具体来说,驱动类型和连接 URL 的对应关系如下:
| MySQL 版本 | 驱动类 | 连接 URL 关键差异 |
|---|---|---|
| 5.x | com.mysql.jdbc.Driver | jdbc:mysql://localhost:3306/dbname |
| 8.x | com.mysql.cj.jdbc.Driver | 需要加 serverTimezone 参数 |
如果你的 MySQL 是 8.0,但是驱动包用的还是旧的 5.1.x,可能会遇到比较奇怪的行为;反过来,如果你用 8.x 的驱动去连 5.7 的数据库,倒是基本兼容。所以我的习惯是:如果是新项目,一律用官方最新的 8.x 驱动,省心。
获取驱动包的几种方式,我也列一下:
- 去 Maven 中央仓库下载
mysql-connector-j-8.0.x.jar,然后放到项目的 lib 目录。 - 用 Maven 构建项目时,直接在
pom.xml里加依赖:
xml复制<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
如果你是手动导入 jar 包的“非 Maven 项目”,记得在 IDEA 里右键 jar 包,选 Add as Library,否则编译会报找不到包。
2.2 连接 URL 的每个参数到底在干什么
很多教程给了连接 URL,但没人告诉你那一串参数有什么用。我在这里拆一下最常用的几个,以后你遇到问题也知道该调谁。
java复制String url = "jdbc:mysql://localhost:3306/blog_demo"
+ "?useUnicode=true"
+ "&characterEncoding=utf8"
+ "&useSSL=false"
+ "&serverTimezone=Asia/Shanghai"
+ "&allowPublicKeyRetrieval=true";
useUnicode=true和characterEncoding=utf8:解决中文乱码的关键。加上之后,客户端发给 MySQL 的 SQL 语句和读取的数据都会用 UTF-8 编码。useSSL=false:MySQL 8.0 默认开启 SSL,但你本地开发根本没有证书,不关掉会报 SSL 连接警告,虽说一般是 warning,但日志会非常吵。serverTimezone=Asia/Shanghai:MySQL 8.0 的驱动强制要求设置时区,不加会直接报The server time zone value '�й���ʱ��' is unrecognized。这里的乱码其实是“中国标准时间”的编码问题,设成Asia/Shanghai是通用做法。allowPublicKeyRetrieval=true:使用 MySQL 8.0 默认的caching_sha2_password认证插件时,客户端需要先从服务器获取公钥,这个参数不加会报Public Key Retrieval is not allowed。
连接参数看着不起眼,但每一个都是在实际报错中总结出来的。建议你把这一串直接复制到自己的工具类里,能少走很多弯路。
3. 从建库到完整增删改查的实操
3.1 建库建表 SQL
在写 Java 代码之前,先把数据库准备好。我这里建一个简单的用户表,字段不要太多,方便演示。
sql复制CREATE DATABASE IF NOT EXISTS blog_demo DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE blog_demo;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT
