首页 / 资讯中心 / 文章详情

MySQL 8.0 JDBC驱动Jar包实战:下载、配置与排错指南

MySQL 8.0 JDBC驱动Jar包实战:下载、配置与排错指南 ★ FEATURED ARTICLE
“MySQL 8.0版本JDBC驱动Jar包”这听起来像是一个非常小的技术问题但实际情况是我亲眼见过不止一个项目在数据库从5.7升级到8.0之后应用层迟迟起不来最后定位到的原因就是这个驱动Jar包没有换对。更夸张的是有的人明明换了8.0的Jar写连接串的时候还照着老文档抄照样报错。这篇文章不绕弯子直接把MySQL 8.0版本的JDBC驱动从下载、引入、配置到排错讲完适合正在升级数据库、新建项目选型或者只是想把驱动换新的人。1. 先搞明白为什么MySQL 8.0的驱动和以前不是一回事1.1 驱动类名变了老一套直接失效在MySQL 5.x时代大家写JDBC连接的时候固定两行代码Class.forName(com.mysql.jdbc.Driver); Connection conn DriverManager.getConnection( jdbc:mysql://localhost:3306/testdb?useSSLfalsecharacterEncodingutf8, root, 123456);这个com.mysql.jdbc.Driver是MySQL 5.x以及更早版本驱动的主类名。到了MySQL 8.0官方把驱动类迁移到了com.mysql.cj.jdbc.Driver这个包名是带cj的含义就是“Connector/J”的新版实现。如果你只换了Jar包但是代码里的Class.forName还写着老名字程序启动时大概率会抛ClassNotFoundException虽然8.0驱动为了兼容还在驱动Jar里保留了旧类的引用但会打出弃用警告而且某些框架的自动检测逻辑会因此走弯路所以不要觉得能跑就是没问题。需要说明的是现在JDBC 4.0以上的规范支持DriverManager自动加载驱动很多场景下可以省略Class.forName但如果你用的还是老项目、老代码风格请老老实实把类名改成com.mysql.cj.jdbc.Driver。1.2 8.0驱动的坐标也变了Maven依赖容易抄错这是另一个非常容易踩的坑。如果你去Maven中央仓库搜索“mysql-connector-java”会发现老坐标dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency这个坐标在8.0.33之后基本停止更新了。官方从8.0.31左右开始推荐新坐标dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId version8.0.33/version /dependency再往后8.1、8.2、8.3、8.4这些版本都只有com.mysql:mysql-connector-j这个新坐标。我建议你从现在开始统一使用新坐标因为旧坐标未来不会再收到更新而且新坐标和旧坐标在同一个版本号上的Jar内容基本一致没什么理由继续守着旧的写错。2. 获取MySQL 8.0 JDBC驱动Jar包的几种方式2.1 最推荐通过Maven或Gradle管理依赖不管你是Spring Boot项目还是普通Java工程我都推荐用构建工具来管理驱动包而不是手工下载Jar。手工下载的问题很明显版本容易记错、团队其他人拿到的是不是同一个版本没保证、升级的时候还要重新替换。用Maven就一行dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId version8.4.0/version /dependencyGradle对应的写法implementation com.mysql:mysql-connector-j:8.4.0这里顺便提一下版本选择。如果你追求稳定我推荐8.0.33加上配置里的serverTimezone、useSSL、allowPublicKeyRetrieval参数后面会讲。如果想用更新的LTS可以关注8.4.x。不要盲目追求最新版本因为驱动版本太新时如果连接的是老版本MySQL服务器某些行为差异可能会让你排查半天。2.2 非Maven项目直接下载Jar文件有些老项目用Eclipse或IDEA管理没有引入Maven这种时候就得直接下载Jar包。打开Maven中央仓库的搜索页面搜mysql-connector-j然后选择你需要的版本下载.jar文件即可。文件大小大概2MB多不算大。下载完之后在IDEA里把Jar文件拷到项目根目录下新建的lib文件夹然后右键Jar包选择“Add as Library”搞定。Eclipse用户则在项目属性里的“Java Build Path”中添加外部Jar。我这里想多说一句用这种方式管理依赖的团队我强烈建议把Jar包放到一个统一的目录中并且在项目文档里记录版本号否则半年之后没人记得当前用的具体是什么版本排查问题时就会很痛苦。2.3 离线环境怎么搬驱动有的公司生产网段和公网是隔离的开发机上不能直接去中央仓库拉依赖这时候需要提前把Jar包准备好。你可以在一台能联网的机器上通过Maven命令把Jar以及依赖一次性拉下来mvn dependency:get -Dartifactcom.mysql:mysql-connector-j:8.0.33或者直接用浏览器下载Jar文件拷贝到离线环境的本地仓库目录~/.m2/repository/com/mysql/mysql-connector-j/8.0.33/下。注意如果用的是mysql-connector-java旧坐标目录是mysql/mysql-connector-java别放错位置。离线环境最容易出现的问题就是“我明明放了Jar怎么还是ClassNotFound”多半是放到了错误坐标对应的目录Maven找不到所以请务必检查本地仓库中的路径是否和GAV完全对应。3. 连接串与核心参数设置直接决定能不能连上3.1 URL格式和驱动类名对照MySQL 8.0驱动的URL格式整体还是jdbc:mysql://主机:端口/数据库名?参数1值1参数2值2端口默认3306数据库名可写可不写。关键区别体现在参数上。一个典型的、能稳定连接MySQL 8.0的URL如下jdbc:mysql://127.0.0.1:3306/testdb?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue有人会发现以前5.x时代不写serverTimezone和allowPublicKeyRetrieval也能连上为什么到了8.0就必须加因为MySQL 8.0的默认认证插件变成了caching_sha2_password和5.x时代的mysql_native_password不一样。当客户端没有使用SSL连接时如果服务器需要返回公钥来走RSA加密传输密码JDBC驱动默认不允许直接向服务器请求公钥所以会报“Public Key Retrieval is not allowed”这时候就需要显式设置allowPublicKeyRetrievaltrue。3.2 三个最容易出错的参数serverTimezone、useSSL、allowPublicKeyRetrievalserverTimezone驱动拿到数据库连接后会读取服务器时区来决定JDBC层的时间转换行为。如果MySQL服务器时区设置为CST或者SYSTEM代表系统时区而驱动无法解析就会出现The server time zone value CST is unrecognized or represents more than one time zone.解决办法有两个我更推荐在URL里显式指定serverTimezoneAsia/Shanghai注意不要写GMT8这种带加号的形式URL中会被解析成空格。当然你也可以修改MySQL服务器的global time_zone但那会影响所有客户端属于数据库端改动很多时候没法按你的意愿来。所以还是靠JDBC参数解决最灵活。useSSLMySQL 8.0驱动默认useSSLtrue但如果你连的是内网数据库而且没有配置证书就会看到一串WARN日志大意是不验证服务器身份就建立了SSL连接。这种警告不会让程序挂掉但会让人觉得不安心。最省事的办法就是useSSLfalse如果你的公司要求数据库连接必须走加密那就不要设置false而是应该在数据库端配置好证书然后在JDBC URL里指定sslModeVERIFY_CA以及trustCertificateKeyStoreUrl等参数。对于绝大多数内部应用来说内网直连加上useSSLfalse是常见的最简方案。allowPublicKeyRetrieval前面已经提过这个参数主要是配合caching_sha2_password认证插件使用。如果你的MySQL 8.0用户采用的还是mysql_native_password不设置也可以但既然数据库都升级到8.0了我建议直接设置allowPublicKeyRetrievaltrue避免未来用户更换认证插件时又突然连不上。3.3 连接池场景下的驱动配置现在大多数应用不会直接用DriverManager.getConnection而是通过HikariCP、Druid或者DBCP拿连接。这时候有两点容易搞混Spring Boot 2.x及以上版本如果没有手动指定会通过自动检测找到驱动但如果你配置了spring.datasource.driver-class-name请一定写新类名spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver spring.datasource.urljdbc:mysql://127.0.0.1:3306/testdb?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue spring.datasource.usernameroot spring.datasource.password123456在HikariCP的Java配置中一定要把URL放到jdbcUrl而不是url里否则HikariCP不会用你的值。如下HikariConfig config new HikariConfig(); config.setJdbcUrl(jdbc:mysql://127.0.0.1:3306/testdb?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue); config.setUsername(root); config.setPassword(123456); config.setDriverClassName(com.mysql.cj.jdbc.Driver);这也是很多Spring Boot项目“配了URL但连不上”的经典原因之一。4. 从零接入一个项目的完整操作流程4.1 Spring Boot项目实战假设你新建了一个Spring Boot项目要连接MySQL 8.0完整步骤如下。第一步在pom.xml中引入依赖。如果项目继承自spring-boot-starter-parent你甚至可以不写版本号直接靠Spring Boot的依赖管理决定dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency注意scoperuntime。很多人喜欢把驱动放在compile作用域也没有大问题但runtime更语义化因为你的代码通常不会直接引用驱动类。第二步在application.yml里配置数据源spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/testdb?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltruerewriteBatchedStatementstrue username: root password: 你的密码第三步启动项目并观察日志。正常启动时控制台会打印HikariCP的连接池信息比如“HikariPool-1 - Start completed.”。如果失败优先看Caused by之后的内容不要再翻前半部分堆栈了。4.2 原生JDBC方式接入在没有框架的老项目中使用MySQL 8.0驱动连接数据库逻辑依然清晰import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class JdbcTest { public static void main(String[] args) throws Exception { String url jdbc:mysql://127.0.0.1:3306/testdb ?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue; try (Connection conn DriverManager.getConnection(url, root, 123456); Statement stmt conn.createStatement(); ResultSet rs stmt.executeQuery(SELECT VERSION() AS v)) { while (rs.next()) { System.out.println(MySQL Version: rs.getString(v)); } } } }这段代码里的try-with-resources会在JDK 7及以上自动关闭连接、语句和结果集避免资源泄漏。如果你还在用老式写法请至少保证在finally中释放资源。运行之后如果控制台输出MySQL Version: 8.0.x说明驱动Jar和连接配置都没问题。4.3 验证驱动版本是否真的生效很多问题出在“工程里有多个MySQL驱动Jar”比如运行时实际用的是老驱动你改造了半天也没用。可以用Java代码来快速确认当前实际加载的类System.out.println(Class.forName(com.mysql.cj.jdbc.Driver));或者更直接一点在代码里打印驱动的版本信息java.sql.Driver driver DriverManager.getDriver(jdbc:mysql://127.0.0.1:3306/testdb); System.out.println(driver.getClass().getName());如果你看到输出是com.mysql.cj.jdbc.Driver就是新驱动。如果是com.mysql.jdbc.Driver说明Jar没有替换干净。这个排查思路在遇到“明明改了pom却还是老行为”时非常有用。5. 高频问题与排查技巧实录5.1 问题速查表我把最常见的问题和对策整理成一个表格方便你遇到问题时直接对照现象根本原因解决方案ClassNotFoundException: com.mysql.jdbc.Driver代码或配置仍使用旧类名改成com.mysql.cj.jdbc.DriverPublic Key Retrieval is not allowedMySQL 8.0默认认证插件是caching_sha2_password且驱动未获准获取公钥URL加allowPublicKeyRetrievaltrueThe server time zone value xxx is unrecognized驱动无法解析数据库服务器时区URL加serverTimezoneAsia/ShanghaiEstablishing SSL connection without servers identity verification is not recommended8.0驱动默认开启SSL但未配置证书内网环境加useSSLfalse生产环境应配置证书Cannot load driver class: com.mysql.cj.jdbc.Driver驱动Jar未正确引入或版本过旧确认Maven依赖存在或手动引入Jar后重新构建Access denied for user rootlocalhost账号密码、主机授权问题检查MySQL用户表和host授权确认密码正确5.2 多个驱动Jar包冲突的处理这是Java后端项目非常经典的坑。有些老项目在WEB-INF/lib下放了一个mysql-connector-java-5.1.x.jar同时Maven又引入了8.x驱动两个Jar都会注册java.sql.Driver而你真正调用的时候可能由类加载顺序决定了使用哪个行为难以预料。解决思路是先通过前面提到的方式打印实际加载的Driver类名如果发现是老驱动优先把Maven依赖和lib目录中的老Jar统一成新版本千万不要两个都保留。对于Tomcat等Web容器还要特别注意lib目录和WEB-INF/lib的隔离关系最稳妥的做法是只保留一处。5.3 版本匹配速查驱动支持哪些MySQL Server关于驱动与Server版本的对应关系我见过不少人把connector-j版本和mysql server 8.0强行划等号认为只有版本号一致才能连。其实不是这样。官方支持的矩阵中Connector/J 8.0.x既可以连接MySQL 5.7也可以连接MySQL 8.0Connector/J 8.1以上同样向后兼容老版本Server。反过来老驱动5.1.x虽然连接MySQL 8.0通常也能跑但身份认证、字符集、时区和性能方面都有隐患能不用就不用。我的建议是驱动版本不低于8.0.28优先用8.0.33或更高连接MySQL 5.7/8.0都没问题。如果你的数据库是企业版或其他发行版兼容性差距也不大但升级驱动前后要做一次连接测试这是最保险的做法。5.4 我踩过的坑连接串里藏着看不见的字符有一次项目排查到半夜MySQL连接时好时坏最后发现URL里serverTimezoneAsia/Shanghai的等号附近混进了一个不可见字符是复制文档时带进来的。这种问题特别难发现因为你肉眼看不到。我养成了一个习惯连接串一旦写好先用文本编辑器的“显示所有字符”检查一遍再去代码里粘贴。另外一个相关的坑是参数值里的在XML配置中要写成amp;否则XML解析直接报错Spring配置文件中尤其常见。6. 关于驱动升级最后再提几条实用建议除了上面这些具体操作我还想分享几个容易忽略的细节这些都是在真实项目中积累出来的经验。第一驱动Jar包的版本号不要写动态版本比如8.0.。这种写法虽然本地构建方便但可能某一天拉到一个不兼容的新版导致生产环境行为突变。锁定具体版本号是最起码的习惯。第二如果使用的是Spring Boot注意启动时如果看到Spring Boot 3.x的潜在版本冲突请关注它默认依赖的驱动版本。Spring Boot 3.x基于Jakarta EE数据库驱动本身的依赖变化不大但如果你自定义了依赖版本仍然要以“最终生效的那个版本”为准而不是看pom.xml里声明了哪个。用mvn dependency:tree检查实际依赖是一个好习惯。第三对于大流量应用我强烈建议开启批量重写参数rewriteBatchedStatementstrue这个参数会让addBatch方式的批量插入自动合并成多值insert性能提升非常明显。再配合cachePrepStmtstrueuseServerPrepStmtstrue可以改善预编译语句的缓存效果。不过参数也不是越多越好每加一个都要知道它解决什么问题否则出了问题反而无从查起。最后如果你正在从旧驱动往MySQL 8.0驱动迁移不要只改依赖不测功能。至少把启动、登录、列表查询、写操作这几条链路完整跑一遍因为连接参数的变化可能影响到时间字段的读取方式、特殊字符的写入方式。一次升级看似简单真正稳落地靠的还是细心验证。以上说的这些都是我在实际项目中反复用过并且确认有效的做法。MySQL 8.0的JDBC驱动本身不复杂但围绕Jar包版本、连接串参数和类加载机制展开的坑确实不少。你只要把这次提到的几个关键点记牢——类名用com.mysql.cj.jdbc.DriverURL补全serverTimezone、useSSL、allowPublicKeyRetrieval依赖坐标尽量用com.mysql:mysql-connector-j——大概率能避开九成以上的连接问题。如果还是遇到奇奇怪怪的报错按照文中的排查表一步步查总能在容器、依赖和连接串三个层面找到答案。
阅读完成 · 觉得有帮助?
咨询建站