☰
MySQL Connector/J:mysql-connector-java与mysql-connector-j坐标迁移全指南
2026/10/10 7:03:50 网站建设 项目流程

直接说结论:mysql-connector-java和mysql-connector-j并不是两个不同的数据库驱动,而是同一个 MySQL Connector/J JDBC 驱动的两种 Maven 坐标。前者是老名字,后者是官方从 8.0.31 版本开始启用的新名字。旧坐标在 8.0.33 发布之后停止更新,后续的功能迭代、安全修复、新版本号体系全部落到了新坐标上。但驱动类名、JDBC 连接串、API 用法完全一致,绝大多数项目迁移时只需要改一下pom.xml或build.gradle里的依赖声明,代码一行都不用动。这篇文章我会把这两个名字的来龙去脉、实际差异、迁移步骤和我踩过的坑一次讲清楚,给正在做 Java + MySQL 开发的人一个能直接照抄的结论。

1. 先搞清楚:这两个名字指的是同一个驱动

1.1 Connector/J 在项目里到底扮演什么角色

MySQL Connector/J 是 MySQL 官方推出的 Java 版数据库驱动,实现的是 JDBC 规范。Java 程序要连 MySQL,无论你是用DriverManager.getConnection()裸连,还是走 Spring Boot + JPA/Hibernate、MyBatis、MyBatis-Plus,底层真正和 MySQL 实例建立 TCP 连接、发送协议包、解析返回结果的,就是这个驱动。简单说,它就是 Java 应用和 MySQL 之间的“翻译官”。

它的工作流程其实很直白:应用层通过连接池或DriverManager发起连接,驱动把 JDBC 调用翻译成 MySQL 客户端/服务端协议消息,通过网络发给 MySQL。连接起来之后,驱动负责处理认证、字符集、事务状态、结果集元数据这些琐碎但对正确性至关重要的东西。所以,驱动 jar 的版本对不对、依赖打包是否完整,直接影响连接稳定性、传参正确性和安全性。

很多人容易在这里被名字绕晕:mysql-connector-java看起来像“专门的 Java 驱动”,mysql-connector-j看起来像“某个新版本”。实际上它们背后是同一个项目、同一套源码、同一个版本号体系,区别只是发布到 Maven 中央仓库时用的坐标写法发生了变化。

1.2 命名演变的关键时间节点

我梳理了几个关键节点,理清楚之后就不会再混淆:

  • 很长一段时间里,官方发布 Connector/J 用的都是mysql:mysql-connector-java这个坐标,版本从 3.x、5.1.x 一路走到 8.0.x。
  • 2022 年 10 月发布 8.0.31 时,官方宣布启用新坐标com.mysql:mysql-connector-j,并在新坐标下同步发布版本。
  • 旧坐标mysql:mysql-connector-java最后一次发布是 8.0.33(2023 年 1 月),之后不再出新的版本。
  • 后续的 8.0.34、8.1、8.2、8.3、8.4 LTS、9.x 等版本,都只以com.mysql:mysql-connector-j发布。

换句话说,如果某个项目里写的还是mysql:mysql-connector-java:8.0.33,那已经是旧坐标的“绝版”版本;如果看到com.mysql:mysql-connector-j:8.4.0,这是新坐标下的长期支持版本。这两者本质是同一个驱动,只是时代不同、名字不同。

2. 表面与本质:坐标不同,功能几乎相同

2.1 一张表看懂 Maven 坐标差异

对比项旧坐标新坐标
groupIdmysqlcom.mysql
artifactIdmysql-connector-javamysql-connector-j
起始版本很早(3.x 时代就有)8.0.31
旧坐标最终版本8.0.33仍在持续发布
驱动类名com.mysql.cj.jdbc.Drivercom.mysql.cj.jdbc.Driver
JDBC URL 前缀jdbc:mysql://jdbc:mysql://
对应项目MySQL Connector/JMySQL Connector/J

从表里能看到,功能层面它们没有“型号”上的差异。8.0.x 的驱动类名都是com.mysql.cj.jdbc.Driver,连接串格式也是jdbc:mysql://主机:端口/库名?参数。所以哪怕你直接把手头项目从旧坐标切到新坐标,只要驱动版本号没有跨大版本(比如从 5.1 直接跳到 8.x),Java 代码基本不需要改。

2.2 驱动类名和连接串为什么不用动

这里专门说一下“代码不用改”的原因。JDBC 4.0 之后,驱动 jar 通过META-INF/services/java.sql.Driver做服务发现,Java 运行时会自动加载驱动。很多项目里已经不需要再写Class.forName("com.mysql.cj.jdbc.Driver")这种代码了。但如果你保留了这行,注意 8.x 的类名是com.mysql.cj.jdbc.Driver,别和 5.x 时代的com.mysql.jdbc.Driver搞混。

这一点和坐标新旧没有关系:8.0.30 用旧坐标,类名是com.mysql.cj.jdbc.Driver;8.0.31 用新坐标,类名还是com.mysql.cj.jdbc.Driver。真正容易踩坑的是从 5.1.x 直接升到 8.x 的场景,类名从com.mysql.jdbc.Driver变成了com.mysql.cj.jdbc.Driver,配置里没改就会直接报ClassNotFoundException。

JDBC URL 同样不变,常见的写法是:

jdbc:mysql://localhost:3306/my_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai

useSSL/sslMode、serverTimezone、allowPublicKeyRetrieval、characterEncoding、rewriteBatchedStatements这些常用参数,在新旧坐标下语义完全一致,迁移时不需要调整。

2.3 真正的功能差异:依赖打包策略变了

如果只看坐标和类名,会觉得这纯粹是一次“改名运动”。实际上有一个值得关注的变化,就是依赖打包策略。

旧坐标下的mysql-connector-java并不是一个完全自洽的 jar。它的 POM 对外声明了第三方依赖,最典型的是com.google.protobuf:protobuf-java,这是 X DevAPI 也就是 MySQL X 协议能力需要用到的库。如果你的项目使用 X Protocol 连接(mysqlx://这种协议),用旧坐标时往往还要手动补 protobuf 依赖。更麻烦的是,当项目里其他组件也用 protobuf,且版本和驱动要求的版本冲突时,会出现各种奇怪的NoClassDefFoundError或者“方法找不到”之类的问题。

新坐标com.mysql:mysql-connector-j从 8.0.31 开始改成了“自包含”的打包方式:把 X Protocol 需要的 protobuf 等第三方类重新定位(relocate)后打进驱动 jar 里。这样带来的直接好处是:引入驱动时不再需要额外声明一堆间接依赖,jar 扔到 classpath 就能用;同一个应用里出现多个 protobuf 版本互相踩踏的概率也大幅降低。代价就是 jar 体积变大了一些,因为内部多了被重新定位的类。

用 Maven 查看依赖树能直观感受到这个差异。旧坐标的依赖树下会挂着com.google.protobuf:protobuf-java,新坐标的依赖树基本是干净的,几乎没有第三方 compile 依赖。这一点对于用mvn dependency:tree排查冲突的人来说,区别非常明显。

3. 为什么官方要改坐标:三个必须知道的背景

3.1 统一 Maven 命名空间

MySQL 官方在 Maven 上发布的 Java 相关构件不少,但历史上命名比较散。mysql-connector-java的 groupId 是mysql,看起来像是一个非官方组织或个人维护的构件。改成com.mysql之后,group 反域名命名规范和 Java 社区主流习惯一致,也能让使用者一眼看出这是官方发布的东西。这个变化本质上是一次“身份标识”的规范化,类似把一个项目从个人命名空间挪到官方命名空间。

从使用者的角度讲,groupId 变了对代码没有任何影响,但会让依赖管理更清晰。尤其是在大型多模块项目里,排查“这个 jar 到底是谁家的”会方便很多。

3.2 让驱动变成一个自包含构件

旧坐标时代的 Connector/J 虽然功能完整,但依赖没有被“隔离”。最典型的就是 protobuf。如果你只是用传统 JDBC 方式连 MySQL,可能根本感知不到 protobuf 的存在;但只要用到 X DevAPI,旧坐标就需要额外引入 protobuf-java,版本还得小心对齐。

新坐标从 8.0.31 开始把第三方类 relocate 进自身 jar,相当于把一个需要“外部零件”的套装变成了“拆箱即用”的成品。这个设计对两类人特别友好:一类是打 fat jar 或 shaded jar 的部署场景,少一个间接依赖就少一个冲突源;另一类是离线环境、内网私服环境,构件越自包含,拉依赖越省事。

3.3 弃用规则与版本节奏

MySQL 官方对 Connector/J 的版本节奏也有调整。以前 8.0.x 一路往下推,很多用户分不清“驱动版本”和“MySQL 服务器版本”的对应关系。现在 Connector/J 跟随 MySQL 的版本策略,分长期支持版(LTS)和创新版(Innovation)。LTS 版本如 8.4.x 适合生产环境,创新版本如 9.x 适合尝鲜和验证新功能。

旧坐标停止在 8.0.33,意味着这个坐标下不会再有新的安全补丁和新特性。如果你的项目还在锁定mysql:mysql-connector-java,并且安全扫描工具开始对旧版本报高风险项,通常的解决办法就是切换到新坐标、升级到最新 LTS 版本,而不是继续在旧坐标里找更高版本号。

4. 实操迁移:从旧坐标切到新坐标

4.1 Maven 项目替换步骤

在pom.xml里找到旧的依赖声明,把整段替换掉。旧写法:

<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency>

新写法:

<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>8.4.0</version> </dependency>

替换后建议执行一次完整构建确认没问题:

mvn clean verify

如果项目里还有别的模块或父 POM 引用了mysql:mysql-connector-java,可以用下面的命令查一下谁还在依赖它:

mvn dependency:tree -Dincludes=mysql:mysql-connector-java

查出来之后,在对应间接依赖里加 exclusion,避免新旧两个 jar 同时出现在 classpath。

4.2 Gradle 项目替换步骤

Gradle 项目的改法更简单。旧写法:

implementation 'mysql:mysql-connector-java:8.0.30'

新写法:

implementation 'com.mysql:mysql-connector-j:8.4.0'

改完可以用下面命令检查依赖情况:

./gradlew dependencies --configuration runtimeClasspath | grep mysql

重点确认runtimeClasspath里只出现一个 MySQL 驱动坐标。如果新旧坐标同时出现,说明有某个库通过传递依赖把旧坐标带进来了,需要在该库的依赖声明里排除mysql:mysql-connector-java。

4.3 Spring Boot 与 MyBatis 等框架中的迁移要点

如果你用的是 Spring Boot,连接配置里的driver-class-name不需要动,仍然是:

spring.datasource.url=jdbc:mysql://localhost:3306/my_db?useSSL=false&serverTimezone=Asia/Shanghai spring.datasource.username=root spring.datasource.password=your_password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

需要注意的是,Spring Boot 不同版本对 MySQL 驱动坐标的管理方式有差异。部分版本的依赖管理(dependency management)可能还在使用旧坐标mysql:mysql-connector-java并管理版本号。如果你在 Spring Boot 项目里手动覆盖驱动版本,要连坐标带版本一起改,只改 version 属性而坐标没换,并不会真正切到新构件。

用 MyBatis 或 MyBatis-Plus 的项目同理:SqlSessionFactory配置、Mapper XML 里的内容完全不受影响,改依赖坐标后重新启动应用验证连接即可。如果你用的是 JPA/Hibernate,注意方言配置还是org.hibernate.dialect.MySQLDialect这类,和驱动坐标无关。

4.4 连接参数兼容性检查清单

迁移后最容易出问题的其实不是坐标本身,而是连接参数。我列一个常用参数检查清单,照着核一遍基本不会翻车:

参数说明常见坑
useSSL/sslMode是否启用 SSL旧项目可能设置useSSL=false,新版本建议用sslMode=DISABLED或PREFERRED
serverTimezone服务器时区不设置可能报The server time zone value错误
allowPublicKeyRetrieval是否允许获取公钥MySQL 8 默认认证插件为caching_sha2_password,连接工具客户端可能需要true
characterEncoding字符集建议utf8或utf8mb4,避免中文乱码
rewriteBatchedStatements是否重写批量语句批量插入性能优化常用,开启需确认 SQL 语义兼容

这些参数在新旧坐标下没有任何差异,迁移时不需要改,但如果你本来就是从一个很老的项目整体升级,这些才是真正需要花时间核对的点。

5. 踩坑实录与排查速查

5.1 新旧两个 jar 同时出现在 classpath

这是迁移过程中最常见的问题。某天项目里明明只声明了一个新坐标依赖,但启动时出现类似“重复的类定义”或者驱动加载异常的报错,十有八九是有个老库通过传递依赖把mysql:mysql-connector-java带进来了。

排查思路分两步:先用mvn dependency:tree -Dincludes=mysql:mysql-connector-java或 Gradle 的dependencyInsight找到来源,然后在对应的传递依赖上做排除:

<dependency> <groupId>org.example</groupId> <artifactId>some-legacy-lib</artifactId> <exclusions> <exclusion> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </exclusion> </exclusions> </dependency>

排除之后重新构建,确认 classpath 里只剩com.mysql:mysql-connector-j。

5.2 旧坐标 + X DevAPI 时的 protobuf 报错

如果项目使用 X Protocol 连接(比如通过mysqlx://协议或者使用mysql-connector-j的部分高级模块),并且还停留在旧坐标,运行时会遇到类似NoClassDefFoundError: com/google/protobuf/...的报错。这是因为旧坐标下的 protobuf 依赖没有被内置,而你的运行环境里恰好没有这个包。

解决办法有两个:要么切换新坐标,让驱动自带的 relocate 版本生效;要么临时补一个兼容版本的com.google.protobuf:protobuf-java依赖。前者是长期方案,后者只是临时止血。我在实际项目里就遇到过 protobuf 版本和项目内其他组件冲突的情况,最后是直接切到新坐标解决,一劳永逸。

5.3 从 5.1.x 升级到 8.x 时的类名陷阱

这不是坐标新旧的问题,但升级过程中特别容易踩。5.1.x 的驱动类名是com.mysql.jdbc.Driver,8.x 是com.mysql.cj.jdbc.Driver。如果你把 8.x 的 jar 放进了 classpath,但配置里还写着旧的类名,启动时会直接报:

ClassNotFoundException: com.mysql.jdbc.Driver

有些框架(比如老版本 Spring Boot 的自动配置)还会因为找不到驱动类而回退到猜测逻辑,导致连接失败。排查时优先检查driver-class-name、hibernate.connection.driver_class这类配置项。

5.4 迁移后连接报错的排查思路

坐标改完、构建通过,但应用启动时报连接异常,这时候按顺序排查会比较快:

  1. 确认 classpath 里没有旧坐标残留,用依赖树命令验证。
  2. 确认 URL 参数没写错,特别是serverTimezone和useSSL/sslMode。
  3. 确认 MySQL 账号的认证插件。如果是caching_sha2_password,且没有使用 SSL,则通常需要allowPublicKeyRetrieval=true。
  4. 清掉本地 Maven 仓库里的旧缓存,执行mvn -U clean verify重新拉取。
  5. 如果应用服务器有多个模块,检查公共 lib 目录里是否有旧版本的驱动 jar。

5.5 常见问题速查表

现象可能原因处理方式
ClassNotFoundException: com.mysql.jdbc.Driver驱动类名用了 5.x 写法改为com.mysql.cj.jdbc.Driver
The server time zone value ...缺少时区参数URL 加serverTimezone=Asia/Shanghai
Public Key Retrieval is not allowed认证插件为 caching_sha2_password 且未允许获取公钥URL 加allowPublicKeyRetrieval=true
启动时有类冲突告警新旧坐标同时存在排除旧坐标传递依赖
X DevAPI 使用时报 protobuf 缺失旧坐标未内置 protobuf切换新坐标或手动补依赖
依赖树出现两个 mysql 驱动传递依赖引入旧坐标在引入方排除旧坐标

6. 新项目怎么选版本:个人建议

6.1 版本号规则简要解读

MySQL Connector/J 现在的版本号规律可以简单理解成:8.0.x 是成熟稳定的长线版本,8.4.x 是官方标记的 LTS 长期支持版,9.x 这类是创新版本、迭代更快但维护周期可能更短。如果你的项目是生产系统,我建议优先考虑 LTS 系列;如果只是个人学习或验证新功能,用最新的创新版本也没问题。

这和我们选 MySQL 服务器版本是一个思路:生产环境求稳,测试环境可以激进一点。连接参数、驱动类名在不同版本之间是稳定的,所以即使后来想升级版本,改动成本也很小。

6.2 按场景选择依赖坐标

项目状态推荐做法
全新项目直接用com.mysql:mysql-connector-j,选 LTS 版本
老项目用旧坐标且没有异常尽快切到新坐标,至少升级到 8.0.33 以上
安全扫描拦截旧坐标升级到新坐标下受支持的最新 LTS 版本
旧项目暂时不能动构建先记录技术债,安排窗口升级,不建议长期停留在旧坐标

6.3 最后分享一点实际体会

我在实际排查过的项目里,见过最让人头疼的情况不是坐标差异本身,而是项目里同时存在多个版本的 MySQL 驱动 jar,导致排查一个简单的连接问题花掉半天时间。所以我的习惯是:每接手一个 Java 项目,第一件事就是跑一遍依赖树,把所有数据库驱动的坐标、版本列出来确认一遍。这个习惯帮我在后续的升级和排障中省了很多事。

如果你正在做的是新项目,直接一步到位用新坐标;如果是老项目,把这次坐标切换当作一次顺手清理依赖的机会,改完依赖后顺便把多余的传递依赖、过时参数一并清理掉。驱动这个环节稳定了,后面查问题会轻松很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询