MySQL驱动坐标从mysql-connector-java到mysql-connector-j:迁移避坑指南
2026/9/15 22:20:24 网站建设 项目流程

最近连续碰到好几个朋友问我同一个问题:项目里一直在用的 MySQL 驱动,为什么以前 Maven 坐标写的是com.mysql:mysql-connector-java,现在网上到处都变成了com.mysql:mysql-connector-j?还有人从代码片段网站或者 AI 工具里复制了一段依赖,版本号莫名其妙写成了release,Eclipse 直接报maven artifact 'com.mysql:mysql-connector-j:release' cannot be resolved。这个坑我踩过不止一次,今天干脆把mysql-connector-javamysql-connector-j的区别、来龙去脉、替换方法一次讲清楚。不管是维护五年前老项目的老手,还是刚用 Spring Boot 3 起步的新人,这篇文章都能帮你少走弯路。

1. 一次报错引发的疑惑:mysql-connector-java 怎么就成了 mysql-connector-j

1.1 先把报错摆上桌:release 版本号为什么解析不了

很多人第一次接触到mysql-connector-j这个新坐标,不是通过官方文档,而是因为一个编译报错。典型场景是这样的:

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

这段依赖放在 pom.xml 里,Eclipse 或 IDEA 的 Maven 插件会直接报:

maven artifact 'com.mysql:mysql-connector-j:release' cannot be resolved

看到这个报错,很多人第一反应是“这个新坐标是不是不存在”,或者“是不是没有配置仓库”。其实问题出在version字段上:release并不是一个真实的 Maven 版本号。Maven Central 上com.mysql:mysql-connector-j的版本列表里,只有类似8.0.318.0.338.4.09.1.0这种具体版本,没有一个叫release的版本。哪怕你把mysql-connector-java换成mysql-connector-j是对的,只要版本号写成release,一样解析不了。

那为什么网上会有这种写法?主要是一些 IDE 的“从仓库添加依赖”功能、代码片段生成工具,在生成示例时会用release作为占位版本。Maven 老版本里确实支持RELEASE(全大写)这种特殊版本号,用来解析仓库里的最新 release 版本,但从 Maven 3.8 开始这种写法在大多数场景下已经不可用,更别说变成小写的release了。所以看到这个报错不用慌,第一步就是把版本改成实际存在的版本号。

1.2 改名时间线:从 8.0.31 开始的坐标调整

解决了报错,再回到正题:为什么会有mysql-connector-javamysql-connector-j两套 artifactId?

我自己的理解是,这其实是 MySQL 官方在 Connector/J 8.0.31 版本做的一次“名称对齐”。在 8.0.30 及之前,MySQL 官方在 Maven Central 上发布的 JDBC 驱动坐标是:

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

但是从 8.0.31 开始,官方把 artifactId 改成了mysql-connector-j,原因也不复杂:官方在产品下载页面提供的压缩包文件名一直是类似mysql-connector-j-8.0.30.zip的格式,解压后核心 jar 包也叫mysql-connector-j-8.0.30.jar,唯独 Maven 仓库里的 artifactId 叫mysql-connector-java,和实际文件名对不上。时间长了很容易混淆。所以官方借着 8.0.31 的构建重构,把 Maven 坐标统一成了com.mysql:mysql-connector-j,让仓库里的依赖和下载页面的文件命名完全一致。

旧坐标com.mysql:mysql-connector-java在 Maven Central 上的最后一个版本定格在 8.0.30,之后不再更新。如果你在 pom.xml 里继续写旧坐标、试图拉取 8.0.31 或更高的版本,Maven 是找不到的,只会一直停留在 8.0.30。这也是很多老项目升级时发现“我版本号改了但依赖没变”的根源。

2. 新老坐标核心区别拆解

2.1 一眼看懂的对比表

很多人问新老坐标到底差在哪,我用一张表直接列出来,这几种写法都是真实存在过的,注意看清 groupId:

坐标类型groupIdartifactId常见版本范围说明
远古写法mysqlmysql-connector-java5.1.x 及之前老项目非常常见,很多教程还在用
8.0 旧写法com.mysqlmysql-connector-java8.0.x(到 8.0.30)8.0 时代主流写法
8.0.31 新写法com.mysqlmysql-connector-j8.0.31+、8.1.x、8.2.x、8.4.x、9.x当前官方推荐的唯一坐标

从表里能看出来,“新老区别”并不是简单的 artifactId 两个单词不同,它还牵扯到 groupId 的变化。5.x 时代大量项目用的是mysql:mysql-connector-java,到了 8.0 时代官方推广com.mysql:mysql-connector-java,现在又改成com.mysql:mysql-connector-j。如果在网上搜到不同时期的代码片段,会出现好几种组合,这就是大家越搜越乱的原因。

这里有一个很实用的判断方法:只要 pom 里的依赖长这样,基本属于“旧坐标”:

  • mysql:mysql-connector-java:大概率是 5.1.x 时代的老配置。
  • com.mysql:mysql-connector-java:通常是 8.0.30 以前的配置。
  • com.mysql:mysql-connector-j:新项目、当前官方推荐的配置。

2.2 版本怎么选:别把 release 当真版本

新坐标mysql-connector-j从 8.0.31 开始发布,之后一路跟随 Connector/J 的版本节奏。目前线上见到的比较多的稳定版本有8.0.338.0.368.4.0,再往后还有一些 8.1.x、8.2.x、8.3.x 的过渡版本,以及 9.x 系列。

关于选版本,我的习惯是“先看稳定线,再追新功能”。如果项目是生产环境,优先选择 8.0.3x 或 8.4.x 这种经过大量验证的版本,不太建议一上来就追 9.x 大版本。如果项目需要用到新特性,比如支持新版 MySQL 服务的连接特性,再按需选择更高的版本。这个版本选择逻辑其实和 MySQL 服务器本身的双轨制发布策略一致,创新版本可以尝鲜,生产环境求稳才是正道。

另外,版本号建议直接写死具体值,不要用latestrelease这类占位符。只为了“少改一次版本号”而牺牲可复现性,在运维和生产排查时会非常难受。我在实际维护中就遇到过因为版本写成RELEASE,导致某天 Maven 不小心拉到一个新大版本,结果驱动行为和旧版不一致,应用启动后连不上数据库的案例。版本号钉死,是降低事故概率最简单的一招。

2.3 驱动类名和 URL 没变,但有些旧写法真的该改

坐标改了,很多人会担心代码里的 JDBC 配置是不是也要跟着改。实际上,驱动类名和连接 URL 基本不受影响:

  • 驱动类名依然是com.mysql.cj.jdbc.Driver
  • 连接 URL 依然是jdbc:mysql://localhost:3306/yourdb
  • 连接参数、连接池配置、MyBatis 等框架的集成方式,都不用改。

但是有一个“历史遗留写法”需要特别提醒:很多老项目里写的是com.mysql.jdbc.Driver,这个类名在 MySQL Connector/J 5.x 时代是正牌驱动类,到了 8.0 时代就变了。如果你在 8.0.x 或更高版本里继续用这个旧类名,很可能会直接抛出ClassNotFoundException,或者因为驱动初始化失败导致应用起不来。所以升级驱动的时候,顺手把driverClassName一起改成com.mysql.cj.jdbc.Driver。如果你用的是 Spring Boot,把spring.datasource.driver-class-name也一并检查一下。

3. 实操:Maven 和 Gradle 项目里如何正确切换坐标

3.1 Maven 项目的替换模板

新项目也好,老项目升级也好,只要确定要用新坐标,直接把 pom.xml 里的 MySQL 驱动依赖换成下面这样就行:

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

这里有一个细节:如果你原本写的是com.mysql:mysql-connector-java,那么升级时要把artifactIdmysql-connector-java改成mysql-connector-j,同时把版本号改成 8.0.31 或更高。如果你原本写的是mysql:mysql-connector-java,那不只是 artifactId 要改,groupId 也要从mysql改成com.mysql

改完之后,建议执行一次强制刷新,避免 IDE 缓存里还残留旧坐标的信息:

mvn clean compile mvn dependency:tree -Dincludes=com.mysql

如果依赖树里出现的是com.mysql:mysql-connector-j:8.4.0,说明切换成功。如果还是旧的com.mysql:mysql-connector-java:8.0.30,说明有传递依赖或者本地缓存没清干净,需要继续往下排查。

3.2 Gradle 项目怎么写

Gradle 项目里写法和 Maven 类似,只是语法不同:

dependencies { implementation 'com.mysql:mysql-connector-j:8.4.0' }

如果你用的是 Gradle 的 version catalog(就是libs.versions.toml那套),把坐标统一写到目录文件里即可:

[versions] mysql-connector = "8.4.0" [libraries] mysql-connector = { group = "com.mysql", name = "mysql-connector-j", version.ref = "mysql-connector" }

Gradle 里同样不建议用+或者latest.release这类动态版本,原因和 Maven 里不能写release一样,依赖不固定,构建结果就容易“薛定谔”。

3.3 Spring Boot 项目特别注意

Spring Boot 项目要比普通 Maven 项目多留个心眼。因为 Spring Boot 的spring-boot-dependenciesBOM 里已经管理了 MySQL 驱动的版本,你写依赖的时候通常不需要写<version>,让 BOM 统一控制。

这里有个关键点:不同版本的 Spring Boot,BOM 里管理的 MySQL 坐标是不一样的。Spring Boot 2.x 早期版本管理的是mysql:mysql-connector-java或者com.mysql:mysql-connector-java,而 Spring Boot 3.x 以及 2.x 的后期版本已经切换到com.mysql:mysql-connector-j。所以:

  • 如果你在用 Spring Boot 3.x,pom 里写com.mysql:mysql-connector-j且不写版本号,这是最合理的做法,版本由 BOM 负责统一管理。
  • 如果你在 Spring Boot 3.x 项目里继续写旧坐标com.mysql:mysql-connector-java,BOM 里很可能没有这个 artifactId 的版本管理,IDE 会提示“dependency is not managed”,需要你手动写版本号,而且写高了还拉不到,总之很别扭。
  • 如果你还在用 Spring Boot 2.3、2.4 这类比较老的版本,暂时不升 Spring Boot 的话,也没必要强行切新坐标,继续用旧坐标反而少折腾。

我自己在实际迁移中的建议是:如果项目准备升级 Spring Boot 大版本,就踩着这个窗口把 MySQL 驱动坐标一起换掉;如果项目短期内不升 Spring Boot,不动驱动也是可以的,毕竟 8.0.30 这个版本的驱动并没有“立即强制升级”的硬性要求。

3.4 验证依赖是否正确拉取

无论用什么构建工具,切换坐标后都要验证一下拉到的 jar 是不是期望的那个。不要只看 IDE 里不报错就以为是好了,我见过太多“IDE 里显示正常,打包时却带上了旧驱动”的案例。

Maven 项目可以执行:

mvn dependency:tree -Dincludes=com.mysql

输出里会明确显示当前项目的 MySQL 驱动 GAV。如果想再彻底一点,直接去本地 Maven 仓库看 jar 文件:

ls ~/.m2/repository/com/mysql/mysql-connector-j/

如果前面是com.mysql:mysql-connector-j,本地仓库路径就是com/mysql/mysql-connector-j/;如果还是继续用旧坐标,路径则是com/mysql/mysql-connector-java/,两者是不同目录。看到 jar 文件之后,还可以用jar tf命令确认驱动类是否存在:

jar tf ~/.m2/repository/com/mysql/mysql-connector-j/8.4.0/mysql-connector-j-8.4.0.jar | grep "Driver.class"

正常情况下能看到com/mysql/cj/jdbc/Driver.class,这就说明驱动本身是完整的。

4. 常见报错与排查实录

4.1cannot be resolved in Eclipse的完整排查思路

这个报错应该是绝大多数人真正遇到的第一个坎,我把排查顺序从高到低列一下:

  1. 检查版本号是否真实存在。把 pom 里的版本改成8.4.08.0.33这种具体版本。如果版本号是从网上直接复制的,尤其注意是不是写了releaseRELEASElatestLATEST这类“伪版本”。
  2. 检查 IDE 的 Maven 配置。Eclipse 或 IDEA 里配置的 Maven 是不是你自己下载的那个版本,settings.xml里是否配置了镜像仓库。有些公司内网环境用私服代理,私服上没有同步com.mysql:mysql-connector-j这个新坐标,就会报无法解析。这时候需要在私服上加白名单,或者临时使用中央仓库拉取验证。
  3. 执行强制更新。Eclipse 里右键项目,选择 Maven -> Update Project,勾选 Force Update;IDEA 里点击 Maven 面板的刷新按钮还不够,最好执行mvn clean install在命令行里强制拉一次依赖。
  4. 清理本地仓库中的残留缓存。如果之前解析失败过,Maven 会在本地仓库留下.lastUpdated后缀的文件,导致后续一直解析失败。找到~/.m2/repository/com/mysql/mysql-connector-j/目录,把里面的.lastUpdated文件删掉,重新mvn -U dependency:resolve

我实际处理过好几个类似的工单,大部分最后都栽在版本号上。所以看到cannot be resolved先别急着怪网络,先审视 pom。

4.2 两个驱动 jar 同时存在:依赖冲突怎么处理

新坐标更换之后,一个很容易忽略的问题就是“传递依赖把旧驱动又带回来了”。比如某个第三方组件或者老的项目模块里,还写着com.mysql:mysql-connector-java,但你的主项目已经切到了com.mysql:mysql-connector-j。结果打包之后 classpath 里就有两个 MySQL 驱动 jar。

由于两代驱动的主要类名和包路径是相同的,JVM 在加载类时只会从其中一个 jar 里加载com.mysql.cj.jdbc.Driver。到底加载哪一个,取决于 classpath 顺序,这就会导致一种很诡异的现象:本地开发一切正常,打出的生产包偶尔出问题,而且不好复现。

解决思路有两个:

第一,用 Maven 的exclusion把旧坐标排除掉:

<dependency> <groupId>com.example</groupId> <artifactId>some-old-module</artifactId> <version>1.0.0</version> <exclusions> <exclusion> <groupId>com.mysql</groupId> <artifactId>mysql-connector-java</artifactId> </exclusion> </exclusions> </dependency>

第二,在dependencyManagement里统一指定新坐标版本,让传递依赖尽量往新坐标收敛。但要注意,如果传递依赖里面写死了旧坐标,dependencyManagement 并不能把它“变成”新坐标,只能控制它的版本。所以最稳妥的还是把旧坐标直接排除掉。

4.3 运行时 ClassNotFoundException 和 NoClassDefFoundError

如果依赖都拉好了,IDE 也不报错了,应用启动时却报:

java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver

或者:

java.lang.NoClassDefFoundError: com/mysql/cj/jdbc/Driver

这通常是两个原因。

第一个原因:驱动 jar 没有真正进入运行环境。很多人只在 IDE 里编译通过了,但是部署时用的是打包脚本或者 Docker 镜像,镜像里的 classpath 没有包含新坐标的 jar。排查方法是看最终产物(比如WEB-INF/lib或构建产物的依赖目录)里有没有mysql-connector-j-*.jar,如果没有,说明构建配置里还是旧坐标或者漏加了依赖。

第二个原因:类被多个 jar 部分加载了,导致运行时找不到类。这种情况在应用容器里比较常见,比如 Tomcat 的lib目录下有一个老版本驱动,应用中又打进去了新版本驱动。容器类加载器优先加载了容器级别的 jar,但版本过老,里面没有com.mysql.cj.jdbc.Driver这个类。解决方法是把容器lib目录下多余的驱动 jar 移除,保留一个版本即可。

4.4 升级驱动后连接 MySQL 报错的几个小细节

坐标切换成功、驱动也能加载,不代表业务就完全不受影响。从旧驱动升级到新驱动之后,连接 MySQL 时偶尔会遇到几个典型报错,这里分享三个最常见的:

第一个是时区问题。MySQL 8.0 里serverTimezone参数没配好,可能会报:

The server time zone value is unrecognized or represents more than one time zone.

连接 URL 里显式加上时区参数可以解决:

jdbc:mysql://localhost:3306/demo?serverTimezone=Asia/Shanghai

第二个是缓存 SHA-2 认证插件问题。MySQL 8.0 默认使用caching_sha2_password认证插件,部分旧驱动版本无法处理,需要加参数:

jdbc:mysql://localhost:3306/demo?allowPublicKeyRetrieval=true&useSSL=false

注意生产环境不建议把useSSL直接设成false,这只是排查时的临时手段,生产应该配置正确的 SSL 证书或者确认网络环境安全后再考虑。

第三个是 SSL 连接行为变化。新版驱动对 SSL 的默认策略和旧版不同,如果数据库服务器没有配 SSL 证书,连接可能直接失败或告警。连接 URL 里加上useSSL=false或者sslMode=DISABLED可以临时绕过,但还是要根据企业的安全规范来定。

5. 我自己的升级经验

5.1 项目该不该切到新坐标?我给个判断标准

经常有人问“我项目跑得好好的,要不要换mysql-connector-j”。我的判断标准比较简单:

  • 如果是新项目,不需要纠结,直接写com.mysql:mysql-connector-j,版本用当前最新稳定版。
  • 如果老项目在持续迭代,并且未来要升级 Spring Boot 或者 JDK,建议借一次版本升级的窗口一并切过去。
  • 如果老项目只是做维护,没有大版本升级计划,那继续用com.mysql:mysql-connector-java:8.0.30也完全可以,不必为了“新旧”而盲目折腾。

很多问题其实是“版本漂移”造成的,而不是mysql-connector-java这个坐标本身有问题。只要版本锁定、依赖一致、测试充分,旧坐标不会突然坏掉。真正危险的是“想升级,但只改了 artifactId,没改版本号”“想升级,但没清理缓存,导致新旧依赖混在一起”这两类操作。

5.2 我踩过的三个坑

第一个坑,就是版本号写成了release。那次是帮同事排查报错,一看 pom 里写着<version>release</version>,瞬间就知道问题在哪了。这种写法来源很多,但本质都是对 Maven 版本机制不够了解。现在看到release两个字,我基本已经形成条件反射了。

第二个坑,是只改了版本号,没改 artifactId。老项目原本是com.mysql:mysql-connector-java:8.0.30,我想升级到新驱动,就只把<version>8.0.3x</version>,结果 Maven 一直拉不到新版本,编译时间长了还以为是网络问题。后来才反应过来,8.0.31 以后的版本不在旧 artifactId 下发布,必须把 artifactId 一起改掉。

第三个坑,是切换完坐标后没有强制刷新 IDE 缓存。项目里明明已经改成com.mysql:mysql-connector-j了,但 IDEA 仍然显示旧依赖,打包也打的是旧 jar。原因就是持续集成环境里缓存了旧的解析结果。现在我切完依赖之后必定会执行一次mvn dependency:tree验证,别相信 IDE 显示的“亲,已经更新了”。

5.3 升级后建议做一轮回归

只要能正常起服务,MySQL 驱动升级对大部分应用来说影响并不大。但“正常启动”不代表“所有功能都正常”。数据库操作层面,我最少会做一轮包含这些点的回归测试:

  • 基础增删改查是否正常。
  • 事务是否正常提交、回滚。
  • PreparedStatement、批处理操作是否正常。
  • ResultSet的字段类型映射是否正常,尤其是 DATE、DATETIME、DECIMAL 这类容易踩坑的类型。
  • JSON 类型字段(如果 MySQL 5.7+ 或 8.0+)读写是否正常。
  • 连接池的初始化、回收、超时机制是否正常。

其实驱动坐标变化本身并不可怕,新旧版本的核心 API 都是兼容的,最需要留意的反而是连接参数、认证方式和依赖关系这些“外围环境”。把坐标切换当成一次普通的版本升级来对待,流程规范一点,就不会出什么大乱子。

我个人现在处理新项目的风格是这样:pom 里一律写com.mysql:mysql-connector-j,版本号直接钉死到一个稳定版,连接 URL 显式配好serverTimezone,Spring Boot 项目则尽量让 BOM 统一管版本。这套做法替我挡掉了很多隐性问题。如果你也正在被这两个坐标折磨,希望这些经验能帮你少踩几个坑。

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

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

立即咨询