
最近连续碰到好几个朋友问我同一个问题项目里一直在用的 MySQL 驱动为什么以前 Maven 坐标写的是com.mysql:mysql-connector-java现在网上到处都变成了com.mysql:mysql-connector-j还有人从代码片段网站或者 AI 工具里复制了一段依赖版本号莫名其妙写成了releaseEclipse 直接报maven artifact com.mysql:mysql-connector-j:release cannot be resolved。这个坑我踩过不止一次今天干脆把mysql-connector-java和mysql-connector-j的区别、来龙去脉、替换方法一次讲清楚。不管是维护五年前老项目的老手还是刚用 Spring Boot 3 起步的新人这篇文章都能帮你少走弯路。1. 一次报错引发的疑惑mysql-connector-java 怎么就成了 mysql-connector-j1.1 先把报错摆上桌release 版本号为什么解析不了很多人第一次接触到mysql-connector-j这个新坐标不是通过官方文档而是因为一个编译报错。典型场景是这样的dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId versionrelease/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.31、8.0.33、8.4.0、9.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-java和mysql-connector-j两套 artifactId我自己的理解是这其实是 MySQL 官方在 Connector/J 8.0.31 版本做的一次“名称对齐”。在 8.0.30 及之前MySQL 官方在 Maven Central 上发布的 JDBC 驱动坐标是dependency groupIdcom.mysql/groupId artifactIdmysql-connector-java/artifactId version8.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.308.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.33、8.0.36、8.4.0再往后还有一些 8.1.x、8.2.x、8.3.x 的过渡版本以及 9.x 系列。关于选版本我的习惯是“先看稳定线再追新功能”。如果项目是生产环境优先选择 8.0.3x 或 8.4.x 这种经过大量验证的版本不太建议一上来就追 9.x 大版本。如果项目需要用到新特性比如支持新版 MySQL 服务的连接特性再按需选择更高的版本。这个版本选择逻辑其实和 MySQL 服务器本身的双轨制发布策略一致创新版本可以尝鲜生产环境求稳才是正道。另外版本号建议直接写死具体值不要用latest、release这类占位符。只为了“少改一次版本号”而牺牲可复现性在运维和生产排查时会非常难受。我在实际维护中就遇到过因为版本写成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 groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId version8.4.0/version /dependency这里有一个细节如果你原本写的是com.mysql:mysql-connector-java那么升级时要把artifactId从mysql-connector-java改成mysql-connector-j同时把版本号改成 8.0.31 或更高。如果你原本写的是mysql:mysql-connector-java那不只是 artifactId 要改groupId 也要从mysql改成com.mysql。改完之后建议执行一次强制刷新避免 IDE 缓存里还残留旧坐标的信息mvn clean compile mvn dependency:tree -Dincludescom.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 BootBOM 里管理的 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.xpom 里写com.mysql:mysql-connector-j且不写版本号这是最合理的做法版本由 BOM 负责统一管理。如果你在 Spring Boot 3.x 项目里继续写旧坐标com.mysql:mysql-connector-javaBOM 里很可能没有这个 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 -Dincludescom.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的完整排查思路这个报错应该是绝大多数人真正遇到的第一个坎我把排查顺序从高到低列一下检查版本号是否真实存在。把 pom 里的版本改成8.4.0或8.0.33这种具体版本。如果版本号是从网上直接复制的尤其注意是不是写了release、RELEASE、latest、LATEST这类“伪版本”。检查 IDE 的 Maven 配置。Eclipse 或 IDEA 里配置的 Maven 是不是你自己下载的那个版本settings.xml里是否配置了镜像仓库。有些公司内网环境用私服代理私服上没有同步com.mysql:mysql-connector-j这个新坐标就会报无法解析。这时候需要在私服上加白名单或者临时使用中央仓库拉取验证。执行强制更新。Eclipse 里右键项目选择 Maven - Update Project勾选 Force UpdateIDEA 里点击 Maven 面板的刷新按钮还不够最好执行mvn clean install在命令行里强制拉一次依赖。清理本地仓库中的残留缓存。如果之前解析失败过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 groupIdcom.example/groupId artifactIdsome-old-module/artifactId version1.0.0/version exclusions exclusion groupIdcom.mysql/groupId artifactIdmysql-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?serverTimezoneAsia/Shanghai第二个是缓存 SHA-2 认证插件问题。MySQL 8.0 默认使用caching_sha2_password认证插件部分旧驱动版本无法处理需要加参数jdbc:mysql://localhost:3306/demo?allowPublicKeyRetrievaltrueuseSSLfalse注意生产环境不建议把useSSL直接设成false这只是排查时的临时手段生产应该配置正确的 SSL 证书或者确认网络环境安全后再考虑。第三个是 SSL 连接行为变化。新版驱动对 SSL 的默认策略和旧版不同如果数据库服务器没有配 SSL 证书连接可能直接失败或告警。连接 URL 里加上useSSLfalse或者sslModeDISABLED可以临时绕过但还是要根据企业的安全规范来定。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 里写着versionrelease/version瞬间就知道问题在哪了。这种写法来源很多但本质都是对 Maven 版本机制不够了解。现在看到release两个字我基本已经形成条件反射了。第二个坑是只改了版本号没改 artifactId。老项目原本是com.mysql:mysql-connector-java:8.0.30我想升级到新驱动就只把version8.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 显式配好serverTimezoneSpring Boot 项目则尽量让 BOM 统一管版本。这套做法替我挡掉了很多隐性问题。如果你也正在被这两个坐标折磨希望这些经验能帮你少踩几个坑。