ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SpringBoot集成JDBC连接MySQL完整指南:从环境配置到报错排查

SpringBoot集成JDBC连接MySQL完整指南:从环境配置到报错排查 简介适用于 Java 开发者和 Spring Boot 入门用户这套方案围绕使用 JDBC 连接 MySQL 数据库提供了完整可落地的资源包内容涵盖可直接运行的源码、环境配置文件、初始化数据库脚本以及配套驱动和安装工具帮助读者从零搭建开发环境理清 JDBC 连接的核心参数与调用方式。压缩包共 136 个文件以 Java 源码、编译后的 class、XML 与 properties 配置、SQL 脚本为代码主体另有 dll、exe、msi、zip 等运行依赖和安装程序PDF 文档可作为操作说明整体约 637.42MB结构较完整。整个资源包按工程结构组织目录划分清晰便于学习时快速定位代码、配置与工具。已有 598 人学习。资源内通过 Controller、实体类等源码演示了请求处理与数据访问的完整链路可对照改造内置的 dll 和安装包免去手动搜索驱动和运行环境的步骤特别适合需要快速完成 JDBC 接入或排查连接异常的学生、开发人员与运维人员。1. 先说结论这套方案到底解决什么问题很多刚接触 SpringBoot 的兄弟上来就是一顿操作猛如虎新建项目、加依赖、写接口结果到连数据库这一步卡了半天。要么是驱动类找不到要么是连接超时要么是时区报错乱七八糟一堆问题非常打击人。我把这套“SpringBoot JDBC MySQL”的完整链路重新整理了一遍从 JDK 安装、MySQL 8.0 部署、SpringBoot 工程搭建到具体代码实现、常见报错排查全部串在一起附带可以直接运行的源码结构和安装包说明你照着走一遍基本就能跑通。这套方案适合谁两类人。第一类是刚学 SpringBoot 的初学者用它理解“一个 Web 应用到底怎么和数据库对话”这件事比一上来就上 MyBatis-Plus 要清楚得多第二类是公司内网环境受限、没法随便装全家桶的老哥JDBC 是 JDK 自带的规范零额外依赖也能干活是个兜底方案。注意标题里说“带源码和安装包”我这边网盘链接就不放了文章里会把源码的目录结构、每个文件的核心代码、MySQL 安装时的关键选项全部写清楚你照着建一遍等于自己写了一遍源码效果反而更好。这也是我后来才想明白的事——直接下载别人的源码看十遍不如自己敲一遍。2. 环境搭建JDK、MySQL 8.0 与 SpringBoot 版本选择2.1 JDK 安装与环境变量这一步错了后面全完JDK 是跑 Java 项目的地基。很多人觉得“不就是装个 JDK 吗”但实际帮人排查的时候发现一半以上的环境问题出在环境变量配置上。装 JDK 本身没什么技术含量官网下一个安装包一路 Next 就行。但有两个细节值得注意。第一安装路径别带空格和中文。比如C:\Program Files\Java\jdk-17这个路径有空格虽然大多数情况下没问题但有些老项目的脚本会踩坑所以我一般建议直接装到D:\Java\jdk-17这种干净的路径下。第二环境变量要配JAVA_HOME不要只把bin目录加到 Path 里。虽然只加 bin 也能用java -version但很多工具Maven、Tomcat、IDEA是通过JAVA_HOME去找 JDK 的不配这个变量后面 SpringBoot 项目跑起来会各种找不到环境。具体配置步骤右键“此电脑” → 属性 → 高级系统设置 → 环境变量新建一个系统变量变量名JAVA_HOME 变量值D:\Java\jdk-17然后在 Path 中新增一行%JAVA_HOME%\bin。这里有个小技巧配置完环境变量后一定不要直接在当前打开的 CMD 窗口里验证因为环境变量是进程启动时读取的旧窗口不会刷新。关掉重开一个命令行窗口输入java -version和javac -version两个都能正常输出版本号才算配置成功。我遇到过好多次看别人截图明明配了 JAVA_HOME结果验证时还是在老窗口里执行误以为配失败了。2.2 MySQL 8.0 安装时容易忽略的几个坑MySQL 这块推荐直接上 8.0 系列别用 5.7 了。5.7 已经停止官方更新而且 JDBC 驱动的坐标、连接 URL 的参数都略有差异你搜资料的时候很容易混。重点说几个 8.0 安装时比较容易出问题的环节。安装类型选择新手选 Server only 就够了别勾选那些 MySQL Workbench、Connector 之类的组件后面需要用的时候单独装。Workbench 是图形化工具用不用不影响你写代码少装点东西少出问题。认证方式MySQL 8.0 安装到最后一步会让你选认证方式默认是 Use Strong Password Encryption即 caching_sha2_password。这里建议开发环境直接选下面的 Use Legacy Authentication即 mysql_native_password。为什么因为老版本的驱动5.1.x和部分客户端工具只支持老协议你后面连接时会报Unable to load authentication plugin caching_sha2_password。虽然新驱动8.0.x两种都支持但为了避免不必要的折腾开发环境建议直接用兼容模式后面连接时省事很多。Root 密码这玩意儿是真的容易忘。我建议就设一个简单的测试密码比如root或者123456反正是本地开发用不要搞什么强密码策略。真忘了也别慌MySQL 8.0 可以通过skip-grant-tables模式重置但那个流程比较繁琐最好别走到那一步。2.3 SpringBoot 版本别追新稳定才是王道热搜词里有“springboot版本太高”这个关键词我猜很多人遇到过项目结构完全没错但启动报错、依赖冲突最后发现是 SpringBoot 版本太新和本地 JDK 版本不匹配。SpringBoot 3.x 要求 JDK 17 起步如果你还在用 JDK 8那最多只能用到 SpringBoot 2.7.x。所以选版本第一步先看自己 JDK 版本别盲上 3.x。我这套方案用的是SpringBoot 2.7.18 JDK 8/11 均可如果想体验新特性也可以用SpringBoot 3.2.x JDK 17。区别就在于 SpringBoot 3 里javax包名换成了jakartaJDBC 相关代码不受影响但如果你自己引入了某些老库就会碰到ClassNotFoundException: javax.servlet.*之类的问题。还有一个比较隐蔽的坑SpringBoot 2.7.x 默认管理的 MySQL 驱动版本是 8.0.33 左右支持 MySQL 8.0 服务端这个没问题。但如果你本机装的是 MySQL 5.x那就需要手动降驱动版本否则某些语法和认证方式可能不兼容。所以装 MySQL 8.0 SpringBoot 2.7.x 默认驱动版本是最不容易出错的组合。3. 核心实现从依赖到跑通查询的完整代码3.1 pom.xml 依赖长这样少一个都不行先看 Maven 依赖。核心其实就两个spring-boot-starter-jdbc和mysql-connector-j。spring-boot-starter-jdbc会把你需要的DataSource、JdbcTemplate都带进来同时默认引入 HikariCP 连接池这个后面说。MySQL 驱动在 SpringBoot 2.7.x 里 artifactId 是mysql-connector-java版本由父依赖管理不需要显式指定SpringBoot 3.x 里改名成mysql-connector-j同样不用写版本号。parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version relativePath/ /parent dependencies !-- Web 依赖如果用浏览器访问接口就需要 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- JDBC 核心依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-jdbc/artifactId /dependency !-- MySQL 驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency /dependencies这里scope设为runtime是因为编译代码时不需要直接引用驱动类运行阶段才需要。你如果去掉这个 scope 也没问题但保持规范总归是好的。提示如果你用的不是 Maven 而是手动导入 jar 包比如 IDEA 里通过 Project Structure 导入那需要下载mysql-connector-java-8.0.33.jar放到项目的 lib 目录下再引入。不过我建议还是用 Maven 管理依赖手动导入 jar 的方式在团队协作时特别容易发生“我这跑得好好的怎么你这不行”的问题本质上就是 jar 版本不一致。3.2 application.yml 配置项逐一拆解配置是 JDBC 连接的核心每一行都有讲究。我的配置如下server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/test_db?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8allowPublicKeyRetrievaltrue username: root password: root hikari: minimum-idle: 5 maximum-pool-size: 20 connection-timeout: 30000逐个解释关键参数driver-class-namecom.mysql.cj.jdbc.Driver注意是cj这是 MySQL 8.0 驱动的新类名。如果你填com.mysql.jdbc.Driver会报警告但 8.0 驱动里还保留着兼容类能跑但不符合规范。强迫症建议直接用新类名。url 里的参数这是重点中的重点useSSLfalse本地开发直接关掉 SSL。MySQL 8.0 默认开启 SSL 握手你会发现日志里一大堆 SSL 警告看着烦不说还影响连接速度。生产环境再根据网络环境决定要不要开。serverTimezoneAsia/Shanghai指定时区。MySQL 8.0 的 JDBC 驱动要求必须显式设置时区否则会报The server time zone value йʱ is unrecognized那串乱码是中文“中国标准时间”在编码不对时显示出来的很多人卡在这一步。characterEncodingutf8设置字符集避免乱码。注意这里是utf8不是utf-8中间那个横杠在某些解析环境下会出问题。allowPublicKeyRetrievaltrue这个参数是配合前面认证方式提到的caching_sha2_password用的。如果 MySQL 用户用了caching_sha2_password认证且连接时没走 SSL驱动需要向服务器获取公钥来加密密码传输。默认禁止这个行为所以报错Public Key Retrieval is not allowed。你如果安装 MySQL 时选了mysql_native_password不加这个参数也能连但加上它等于多了一层保险。hikari 连接池配置SpringBoot 2.x 默认连接池是 HikariCP性能很猛号称“最快的连接池”。minimum-idle表示连接池最少保持 5 个空闲连接maximum-pool-size表示最大 20 个连接connection-timeout是获取连接的超时时间单位毫秒。这些参数在开发环境用默认值就行但面试时被问到连接池相关概念能说出来这几项的含义会加分不少。3.3 实体类、Repository 层和 Controller 层的完整代码配置写好了接下来写代码。我这里用最简单的三层结构Controller接收请求→ Service业务逻辑→ Repository数据访问。JDBC 的访问方式用 Spring 自带的JdbcTemplate它对原生 JDBC 做了封装省去手动管理Connection、PreparedStatement、ResultSet的脏活累活但又保留了 SQL 的灵活性。先建一个用户表在 MySQL 里执行CREATE DATABASE IF NOT EXISTS test_db DEFAULT CHARACTER SET utf8mb4; USE test_db; CREATE TABLE IF NOT EXISTS t_user ( id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, age INT DEFAULT 0 );然后写实体类User字段对应表结构public class User { private Long id; private String name; private Integer age; // 无参构造、有参构造、getter/setter 省略 // 实际开发中可以用 Lombok 的 Data 注解简化 }Repository 层用JdbcTemplate做查询Repository public class UserRepository { Autowired private JdbcTemplate jdbcTemplate; public ListUser findAll() { String sql SELECT id, name, age FROM t_user; return jdbcTemplate.query(sql, (rs, rowNum) - { User user new User(); user.setId(rs.getLong(id)); user.setName(rs.getString(name)); user.setAge(rs.getInt(age)); return user; }); } public User findById(Long id) { String sql SELECT id, name, age FROM t_user WHERE id ?; return jdbcTemplate.queryForObject(sql, new Object[]{id}, (rs, rowNum) - { User user new User(); user.setId(rs.getLong(id)); user.setName(rs.getString(name)); user.setAge(rs.getInt(age)); return user; }); } public int save(User user) { String sql INSERT INTO t_user(name, age) VALUES(?, ?); return jdbcTemplate.update(sql, user.getName(), user.getAge()); } }这里注意query方法里的RowMapper匿名内部类作用是把查询结果的每一行映射成一个 Java 对象。JDK 8 之后可以用 Lambda 简化上面已经是 Lambda 写法了。这个映射过程新手容易忽略总觉得“查询结果不就应该自动变成对象吗”JDBC 规范里真没这回事每一列都需要手动rs.getXxx()取出来。这也是 JDBC 和 MyBatis 这类 ORM 框架最大的区别。Controller 层很简单写两个 RESTful 接口用来测试RestController RequestMapping(/api/user) public class UserController { Autowired private UserRepository userRepository; GetMapping(/list) public ListUser list() { return userRepository.findAll(); } GetMapping(/{id}) public User getById(PathVariable Long id) { return userRepository.findById(id); } PostMapping(/add) public String add(RequestBody User user) { return userRepository.save(user) 0 ? success : fail; } }启动入口类不用动SpringBoot 的应用主类SpringBootApplication注解会自动扫描配置把DataSource、JdbcTemplate装配好。启动项目访问http://localhost:8080/api/user/list能看到 JSON 数组返回就说明整条链路通了。3.4 手动导入 JDBC 包的替代方案之前提到 IDEA 里导入 JDBC 包这里单独说一下。如果你确实不用 Maven而是想手动把mysql-connector-java.jar导进项目里步骤是IDEA 里File→Project Structure→Modules→ 选中你的模块 →Dependencies→ 点→JARs or directories→ 选中下载好的 jar 包 → 勾选compile级别。这个操作在热词里出现频率挺高很多人直接操作 IDEA 的时候找不到入口。但说实话这个方案只适合应急Maven 才是正道。4. 我第一次跑通时踩过的五个坑比教程更值钱的实战记录4.1 报错 “No suitable driver found” 的真相这个报错几乎是每个 JDBC 新手都会遇到的。看错误全文java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/test_db。它的意思是JVM 在启动的驱动列表里没有找到能解析这个 URL 的驱动。常见原因有三个第一是mysql-connector-java依赖没加进来Maven 坐标写错了导致 jar 没下载第二是驱动类名写错比如 MySQL 5.x 写com.mysql.jdbc.Driver到 8.x 应该用com.mysql.cj.jdbc.Driver第三是 URL 前缀拼错了jdbc:mysql://写成了mysql://或者漏掉jdbc:前缀。不过在实际开发中如果你用的是 SpringBoot 的spring.datasource配置很少会报这个错因为 SpringBoot 会自动注册驱动。反而是手动Class.forName(com.mysql.cj.jdbc.Driver)的代码一旦类名写错立刻就会抛ClassNotFoundException。我的建议是不要手动写Class.forName让 SpringBoot 自己管理驱动加载配置好依赖和 yml 就完事。4.2 Public Key Retrieval is not allowed这个报错的文字很直白“不允许检索公钥”。但理解起来有点绕。简单说MySQL 8.0 默认的caching_sha2_password认证方式在非 SSL 连接下需要客户端向服务器请求一个公钥来加密传输密码。JDBC 驱动出于安全考虑默认禁止这个操作所以你要在 URL 后面显式加上allowPublicKeyRetrievaltrue来允许它。这个报错有个规律有时候第一次连接成功第二次报错。原因是 MySQL 会把客户端的认证缓存一段时间缓存失效后重新认证这时候才需要公钥获取。排查起来比较迷惑解决方案很简单URL 里加上这个参数就一劳永逸。4.3 Communications link failure 到底是什么问题Communications link failure这个报错范围就广了。它本质上是“客户端到服务器的网络链路断了”。常见原因MySQL 服务没启动。Windows 下打开服务管理器services.msc找到MySQL80服务确认状态是“正在运行”。安装 MySQL 的时候有个选项是“配置为 Windows 服务”如果当时没勾选MySQL 不会自动启动需要手动启动。端口被占用。MySQL 默认 3306 端口如果你改了端口URL 里忘记同步修改连不上就报这个错。防火墙拦截。Windows 防火墙默认会拦截外部访问 3306 端口本地连接一般不触发但如果你在虚拟机或者远程服务器上连就得放行端口。服务器 IP 配置问题。URL 里写了localhost但 MySQL 只监听了127.0.0.1或者反过来都有可能出现链路问题。排查办法是命令行执行mysql -uroot -p -h127.0.0.1 -P3306能连上说明 MySQL 本身正常问题出在应用配置。4.4 时区报错和 SSL 警告时区报错前面提到过报错信息长这样The server time zone value ???ú±ê׼ʱ?? is unrecognized or represents more than one time zone.后面那串乱码其实是 GBK 编码的“中国标准时间”被 JDBC 驱动读取时按默认编码解析导致显示乱码。解决方案就是 URL 里加serverTimezoneAsia/Shanghai。SSL 警告是明文写的WARN: Establishing SSL connection without servers identity verification is not recommended.这个警告对功能没有影响但每次连接都刷日志看着碍眼。加useSSLfalse就可以关掉。在本地开发环境数据不经公网传输关掉 SSL 完全没有问题。4.5 SpringBoot 启动报错 name jdbc is not bound in this context这个报错也是不少人的拦路虎。完整报错里通常带有Name jdbc is not bound in this Context。这其实是 JNDI 数据源找不到导致的。SpringBoot 默认不用 JNDI但某些情况下比如你复用了老项目的配置文件里面有spring.datasource.jndi-name之类的配置或者代码里用InitialContext.lookup(jdbc/xxx)去找数据源就会报这个。正常使用 SpringBoot 原生配置不会触发。如果你遇到了检查是不是引入了别人老项目的配置片段。SpringBoot 的默认做法是只认spring.datasource.url这一套不存在 JNDI 的情况。5. 常见问题速查看报错一句话定位为了让你排查更快我把上面这些坑整理成一个速查表建议收藏。实际遇到问题的时候先对照报错关键词查一下能省出大量百度时间。报错关键词原因解决方案No suitable driver found驱动依赖缺失、类名错误、URL前缀错误确认mysql-connector-java依赖存在检查驱动类和 URL 前缀Public Key Retrieval is not allowedMySQL 8.0 缓存认证需要获取公钥URL 加allowPublicKeyRetrievaltrueCommunications link failureMySQL 未启动、端口错误、防火墙拦截确认 MySQL 服务运行中检查端口和防火墙The server time zone value...时区未指定或编码乱码URL 加serverTimezoneAsia/ShanghaiSSL connection without verification连接时未关闭 SSLURL 加useSSLfalse只是警告不影响功能Access denied for user rootlocalhost用户名或密码错误检查 yml 中的username和passwordUnknown database test_db数据库不存在先执行CREATE DATABASE创建库Table xxx doesnt exist表不存在或库用错了检查 SQL 语句确认连接的是对的那个库name jdbc is not bound in this context项目里用了 JNDI 数据源配置排查是否有jndi-name配置改用url配置表格里第三行“Access denied”也值得单独说。如果你密码确认无误但就是连不上检查一下 MySQL 用户的主机限制。本地连接应该是rootlocalhost但如果你用 IP 连而 MySQL 里的 root 用户只授权了localhost也会被拒绝。解决方案是创建允许任意主机访问的用户CREATE USER root% IDENTIFIED BY 你的密码; GRANT ALL PRIVILEGES ON *.* TO root% WITH GRANT OPTION; FLUSH PRIVILEGES;开发环境这么搞问题不大生产环境千万别这等于把数据库裸奔在网络里。6. 一点总结与下一步扩展整套方案跑通以后你会发现 SpringBoot JDBC 这条路其实是理解整个 Java 数据访问体系的基石。JdbcTemplate 的RowMapper机制看懂了 MyBatis 的ResultMap就很好理解DataSource连接池的作用理解了才能明白为什么 MyBatis 和 JPA 都只是“封装”而不是“替代”了 JDBC。以后面试被问“MyBatis 底层是什么”你至少能答上来一句“底层还是 JDBCMyBatis 只是帮你把 SQL 参数绑定和结果集映射做了封装。”就这一句话能和背八股文的人拉开差距。最后分享一个我个人的实操习惯在每个新环境里跑通数据库连接后我会先把最简单的查询接口调通再加连接池配置最后才接 ORM 框架。这样每一层出问题都能定位到具体环节而不是全部堆在一起报错信息一大坨看不过来。这套“先 JDBC 验路、再框架封装”的做法帮我排掉了无数个“看似框架问题实则环境问题”的雷你可以试试。本文还有配套的精品资源点击获取
返回列表