MySQL 驱动里那个 cj 到底是什么?
你一定写过这行代码:
propertiesdriver=com.mysql.cj.jdbc.Driver但你有没有想过,中间那个
cj是什么意思?为什么旧版本是com.mysql.jdbc.Driver,新版本却多了一层cj?
一句话解释
cj 是 Connector/J 的缩写。
Connector/J 是 MySQL 官方为 Java 提供的 JDBC 驱动的正式名称,全称是 MySQL Connector/J 。在 6.0 版本对驱动进行彻底重构时,MySQL 团队将新的核心代码全部放入了 com.mysql.cj.* 这个命名空间下,cj 就此出现在了驱动类名里。
历史背景:一次迟到的大扫除
MySQL 的 Java 驱动从 2000 年就开始存在了,早期代码全堆在 com.mysql.jdbc.* 包下。随着功能越来越多,这个包变得越来越臃肿:
- JDBC 协议实现、连接池、认证插件、异常处理......全部平铺在一个命名空间里
- 代码耦合严重,历史包袱越来越重
- 新的 MySQL 特性(比如 X DevAPI、SHA-2 认证)很难干净地加进去
到了 2016 年,MySQL 团队在 Connector/J 6.0 中对驱动进行了一次彻底的架构重构,核心思路是:
把
cj(即 Connector/J)作为顶层命名空间,在它下面再划分职责清晰的子层。
新旧包结构对比
| 职责 | 旧包名(5.x) | 新包名(6.x / 8.x) |
|---|---|---|
| JDBC 驱动入口 | com.mysql.jdbc.Driver |
com.mysql.cj.jdbc.Driver |
| 异常拦截器 | com.mysql.jdbc.ExceptionInterceptor |
com.mysql.cj.exceptions.ExceptionInterceptor |
| 认证插件 | com.mysql.jdbc.AuthenticationPlugin |
com.mysql.cj.protocol.AuthenticationPlugin |
| 数据源 | com.mysql.jdbc.jdbc2.optional.MysqlDataSource |
com.mysql.cj.jdbc.MysqlDataSource |
| 负载均衡策略 | com.mysql.jdbc.BalanceStrategy |
com.mysql.cj.jdbc.ha.BalanceStrategy |
| 语句拦截器 | com.mysql.jdbc.StatementInterceptorV2 |
com.mysql.cj.interceptors.QueryInterceptor |
可以看到,新架构的分层非常清晰:
com.mysql.cj
├── jdbc/ ← JDBC 协议适配层(对外暴露 java.sql.* 接口)
├── protocol/ ← 底层网络协议、认证逻辑
├── exceptions/ ← 异常体系
├── interceptors/ ← 拦截器
└── jdbc.ha/ ← 高可用、负载均衡
cj 是整个新架构的根命名空间,jdbc 只是其中一个子模块。 这也是为什么驱动类名从 com.mysql.jdbc.Driver 变成了 com.mysql.cj.jdbc.Driver------原来的 jdbc 包整体"下沉"到了 cj 下面。
重构带来了什么
命名变化只是表象,重构本身带来了很多实质性提升:
1. 支持新认证方式 MySQL 8.0 引入了 caching_sha2_password 作为默认认证插件,旧驱动完全不支持,必须重写协议层才能对接。
2. 默认字符集从 LATIN1 改为 UTF-8 旧驱动默认字符集是 LATIN1,中文乱码是常见问题。新驱动默认 UTF-8,符合现代应用的预期。
3. 支持 X DevAPI MySQL 5.7+ 新增了文档型数据库能力,新驱动通过独立的 xdevapi 模块支持这套接口,旧架构根本无处安放。
4. 完整实现 JDBC 4.2 规范 包括更好的时间类型支持(java.time.*)、大对象操作等。
第二次改名:Maven 坐标之变(2022 年)
除了包名,Maven 坐标在 2022 年也改了,但原因完全不同。
| 旧坐标 | 新坐标 | |
|---|---|---|
| groupId | mysql |
com.mysql |
| artifactId | mysql-connector-java |
mysql-connector-j |
这次改名的原因非常朴素:产品名字从来就叫 Connector/J,不叫 Connector/Java。 旧的 mysql-connector-java 这个 artifact ID 从一开始就起错了,只是多年来一直没有机会纠正,借着 2022 年整理内部发布流程的机会,顺手把名字改对了。
从 8.1.0 起,旧坐标彻底停用。现在正确的 Maven 依赖写法是:
xml
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.3.0</version>
</dependency>
时间线总结
2000 年 MySQL Connector/J 诞生,包名 com.mysql.jdbc.*
│
2016 年 Connector/J 6.0 架构重构
│ ↳ 引入 com.mysql.cj.* 命名空间
│ ↳ 驱动类名改为 com.mysql.cj.jdbc.Driver
│ ↳ 旧类名 com.mysql.jdbc.Driver 标记为 deprecated
│
2022 年 Connector/J 8.0.31 发布
│ ↳ Maven 坐标改为 com.mysql:mysql-connector-j
│ ↳ jar 文件重命名为 mysql-connector-j-x.y.z.jar
│
2023 年 Connector/J 8.1.0 发布
↳ 旧 Maven 坐标 mysql:mysql-connector-java 彻底废弃
常见问题
Q:我的项目还在用 com.mysql.jdbc.Driver,会报错吗?
只要你用的 jar 版本是 5.x,就没问题。但如果 jar 升到了 6.x 或以上,就会报 ClassNotFoundException 或打印 deprecated 警告,需要改成 com.mysql.cj.jdbc.Driver。
Q:升级到新驱动需要改 JDBC URL 吗?
通常需要加上时区参数,否则会报错:
properties
# 旧写法(5.x)
url=jdbc:mysql://localhost:3306/mydb
# 新写法(6.x / 8.x)
url=jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai&useSSL=false
Q:Class.forName("com.mysql.cj.jdbc.Driver") 还需要手动写吗?
不需要。从 JDBC 4.0(Java 6)开始,驱动会通过 SPI(META-INF/services/java.sql.Driver)自动注册,Class.forName 这行代码已经是历史遗留写法,可以删掉。
小结
| 问题 | 答案 |
|---|---|
cj 是什么意思? |
Connector/J 的缩写 |
| 为什么改名? | 2016 年架构重构,引入新的分层命名空间 |
| 驱动类名变了什么? | com.mysql.jdbc.Driver → com.mysql.cj.jdbc.Driver |
| Maven 坐标变了什么? | mysql:mysql-connector-java → com.mysql:mysql-connector-j |
| Maven 坐标为何改? | 纠正历史命名错误,与产品真实名称对齐 |
一个小小的 cj,背后是一次关于代码组织和架构清晰度的认真思考。下次再看到这两个字母,你知道它代表的是什么了。