ARTICLE DETAIL

资讯详情

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

SpringBoot连接本地MySQL全流程:配置、CRUD与高频报错排查

SpringBoot连接本地MySQL全流程:配置、CRUD与高频报错排查 先把话说在前头把 SpringBoot 项目连上本地 MySQL听起来真的就是个配置问题但我见过太多同学在这件事上卡两三天。数据库装好了连不上连上了跑不动跑起来了中文乱码折腾一圈最后发现就是 URL 多了个问号少了个参数。这篇文章不搞那些虚的直接带你走一遍“本地 SpringBoot MySQL 从零打通”的完整链路包括 MySQL 8 安装、账号建库、Spring Boot 数据源配置、JdbcTemplate 和 JPA 两条常用路线、完整 CRUD 接口以及我在实际排障中踩过的高频报错。适合第一次接触 JavaWeb 做课程设计、毕业设计的人也适合想把连接池、SSL、时区这些默认行为真正弄明白的半新手。读完不需要再到处搜资料直接对着抄就行。1. 先把手头环境准备好本地 MySQL 与 Spring Boot 工程1.1 MySQL 8 的安装与初始化先说安装。现在的本地开发无脑选 MySQL 8.0 就可以了5.7 虽然坑少但已经过了主力期Spring Boot 3.x 和 MySQL 8 配合起来也更顺。Windows 直接去 MySQL 官网下载 MSI Installer装的时候勾选 MySQL Server 和 MySQL Workbench 就够用其他组件基本用不上。macOS 上我习惯用 Homebrew一条brew install mysql能省掉很多环境变量问题。Linux 服务器环境则根据发行版选apt install mysql-server或yum install mysql-server装完记得看下服务是否自动起来了。安装过程中最容易忽视的是 root 密码。我建议安装时别图方便设空密码后续用命令行也好、用 Navicat 也好都要验证身份。设置好密码后先打开终端确认服务在运行然后执行mysql -uroot -p show databases;如果终端提示mysql: command not found别慌不是没装好是 bin 目录不在 PATH 里。Windows 需要把 MySQL 安装目录下的 bin 路径加到系统环境变量macOS 通过 Homebrew 安装的路径一般是/usr/local/mysql/bin可以用export PATH$PATH:/usr/local/mysql/bin临时加入或者写入~/.zshrc永久生效。这一步不解决后面所有命令行操作都没法做。1.2 建库、建账号别拿 root 直接怼业务很多教程让你直接用 root 连数据库本地练手确实没问题但我不建议原因有两层。第一root 权限过大万一代码里出现误操作比如DROP DATABASE哭都来不及第二当你把项目部署到服务器或者交接给别人的时候业务账号和权限边界能省掉大量私下沟通的麻烦。在 MySQL 里执行下面这段建一个独立库和一个独立账号CREATE DATABASE demo_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER demolocalhost IDENTIFIED BY Demo123456; GRANT ALL PRIVILEGES ON demo_db.* TO demolocalhost; FLUSH PRIVILEGES;建库时我特意写了utf8mb4而不是默认的utf8。这两者的差别很多人不清楚MySQL 的utf8其实是阉割版最多支持 3 字节字符遇到 emoji 或者生僻字直接报Incorrect string valueutf8mb4才是完整版能存下 4 字节字符。你今天建库可能不在乎但保不齐哪天需求里就要存个表情符号。顺便说一句MySQL 8 的默认认证插件是caching_sha2_password我上面建的这个demo用户就是这个认证方式。等会儿 Spring Boot 连接时候可能会碰到 public key retrieval 的问题这里先留个印象第 2 章专门讲。1.3 初始化一个 Spring Boot 工程创建工程最省事的方式是访问 start.spring.io或者直接用 IntelliJ IDEA 里的 Spring Initializr。语言选 Java构建工具选 Maven 或 Gradle这两个都行我下面演示 Maven因为新手照着做最不容易出岔子。版本选择是第一个容易踩坑的地方。Spring Boot 3.x 要求 JDK 17 及以上而很多公司或学校的环境还是 JDK 8这种情况下只能选 Spring Boot 2.7.x。另外 Spring Boot 3 里原来的javax.*包全部换成了jakarta.*你从网上复制旧教程代码时会看到一堆 import 报错如果发现这个现象大概率是版本没对齐。我建议手头环境 JDK 8 就选 2.7.18JDK 17 就直接上 3.2.x 或更新版本。依赖方面至少要有三个Spring Web、Spring Data JPA、MySQL Driver。有人会问我用 JdbcTemplate 是不是就不用选 JPA其实选了 Spring Data JPA 会自动把 JDBC 相关依赖带进来JdbcTemplate 也可以直接用所以本地开发一次性勾上 JPA 不亏。另外想用 MyBatis 的同学注意start.spring.io 上默认没有 MyBatis 的 starter得手动引入第三方依赖这个后面第 3 章细说。2. 连接配置拆解JDBC URL、连接池与三个大坑2.1 application.yml 里到底该写什么项目建好后打开src/main/resources/application.yml有的项目是application.properties都行个人更推荐 yml层级清楚、注释好写把数据库配置写成这样server: port: 8080 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/demo_db?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8allowPublicKeyRetrievaltrue username: demo password: Demo123456 driver-class-name: com.mysql.cj.jdbc.Driver hikari: minimum-idle: 2 maximum-pool-size: 10 idle-timeout: 60000先解释这个url。前半段就是 JDBC 连 MySQL 的固定格式jdbc:mysql://IP:端口/数据库名后半段是一堆参数个个都可能有坑。useSSLfalse表示关闭 SSL本地开发完全没必要加密不然可能报 SSL 协商错误。serverTimezoneAsia/Shanghai解决时区偏差 8 小时的问题JDBC 8.0 默认要求服务端告诉你时区不写它很可能直接抛异常。characterEncodingutf8确保中文能正确编码传输。allowPublicKeyRetrievaltrue则是 MySQL 8 配合caching_sha2_password认证时经常需要的一个开关下面专门讲。2.2 MySQL 8 的 SSL 连接错误与 public key retrieval 问题这是本地开发里出现频率极高的一组报错热搜词里能看到它是有原因的。第一个情况是SSL connection error: Unable to load authentication plugin caching_sha2_password或Communications link failure ... Public Key Retrieval is not allowed。很多人一看到 SSL 三个字母就先慌了觉得是不是要配证书其实本地根本不用。原因在于 MySQL 8 默认使用caching_sha2_password认证当客户端连接没有走 SSL 加密通道时服务端需要把 RSA 公钥发给客户端做密码传输而 JDBC 驱动出于安全考虑默认不自动拉取服务端公钥于是报 “Public Key Retrieval is not allowed”。这个时候加allowPublicKeyRetrievaltrue就是在告诉驱动我是本地连接信任这个服务器允许你把公钥拿过来。同时配合useSSLfalse本地不加密密码传输用 RSA 公钥加密已经够用。生产环境就别天真地照搬了生产该开 SSL 就开 SSL该配 CA 就配 CA。2.3 时区、驱动类名和“localhost 魔咒”时区问题最典型的表现是数据库里存的时间是2024-01-01 12:00:00查出来变成了04:00莫名其妙少了 8 小时。这是因为默认连接时区用的是 JVM 时区而 MySQL 服务端可能是 UTC。统一指定serverTimezoneAsia/Shanghai能直接消掉这个问题不要用什么GMT8之类的写法维护麻烦还容易写错。关于driver-class-nameSpring Boot 会根据 URL 前缀自动推断所以这一行写不写都能跑。但我还是建议写出来特别是排查问题的时候你能一眼确认用的是不是新版驱动com.mysql.cj.jdbc.Driver。老项目里常见的com.mysql.jdbc.Driver是 MySQL 5.x 时代的类名在 MySQL 8 环境下虽然兼容但会打警告本地开发建议直接用新版。还有个魔咒叫“localhost”。JDBC URL 里写localhost和写127.0.0.1有本质区别前者在某些系统上会去尝试连接本地 socket 文件而不是 TCP 端口MySQL 8 的 socket 路径一旦和你系统的默认路径对不上就会出现类似Cant connect to local MySQL server through socket /tmp/mysql.sock的报错。Spring Boot 应用本身没问题但你在排查时如果看到 socket 字样第一反应应该是把连接地址改成127.0.0.1永绝后患。2.4 连接池 HikariCP 和本地参数设置Spring Boot 2.x 以后默认的数据源连接池就是 HikariCP关于它的信息你其实不用知道太多只要理解一件事每次请求数据库都新建连接是非常昂贵的连接池就是提前建好一批连接放那儿循环用。在本地开发环境池子参数不需要太大上面配置里的maximum-pool-size: 10已经绰绰有余因为单机开发没有几十个并发。有的同学喜欢去调整一堆 buffer 参数本地真的没必要保持默认反而更稳。3. 数据库操作三条路线JdbcTemplate、JPA、MyBatis 怎么选3.1 JdbcTemplate简单直接适合快速上手JdbcTemplate 是 Spring 提供的最轻量级的 JDBC 封装。它没有 MyBatis 那套 XML 映射也没有 JPA 那套实体生命周期核心就是JdbcTemplate这个对象提供一堆方法你写 SQL它帮你执行并转换结果。优势在于 SQL 完全可控像select * from这种操作一眼能看明白调优的时候也方便直接套上 EXPLAIN。简单演示一下。在 Spring Boot 里注入JdbcTemplate就可以直接操作Repository public class UserDao { private final JdbcTemplate jdbcTemplate; public UserDao(JdbcTemplate jdbcTemplate) { this.jdbcTemplate jdbcTemplate; } public User findById(Long id) { String sql select id, username, nickname from t_user where id ?; return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper(User.class), id); } public int insert(User user) { String sql insert into t_user(username, nickname) values (?, ?); return jdbcTemplate.update(sql, user.getUsername(), user.getNickname()); } }注意这里我用的是?占位符而不是拼字符串这是防 SQL 注入的基本底线。JdbcTemplate 底层是PreparedStatement参数先预编译再传值你传什么它都当数据处理不会把它拼进 SQL 里。新手最容易犯的错误就是写成jdbcTemplate.update(insert into t_user(username) values ( username ), ...);一旦 username 内容是); DROP TABLE t_user;--整张表就没了。所以不管用什么框架SQL 里凡是外部传入的值一律走占位符或者参数绑定这是永远不能省的规矩。3.2 Spring Data JPA实体为中心写代码最少JPA 的思路是“我不管你怎么建表你只要把类和数据库表对应起来剩下的增删改查由框架生成”。Spring Data JPA 更是把这一套推到了极致你定义接口方法名直接决定 SQL 逻辑。比如findByUsernameSpring 自动帮你翻译成where username ?连 SQL 都不用写。定义实体的样子Entity Table(name t_user) public class User { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; private String username; private String nickname; }然后建 Repositorypublic interface UserRepository extends JpaRepositoryUser, Long { OptionalUser findByUsername(String username); boolean existsByUsername(String username); Query(select u from User u where u.nickname like concat(%, :keyword, %)) ListUser searchByNickname(Param(keyword) String keyword); }这里JpaRepositoryUser, Long的泛型第一个参数是实体类型第二个是主键类型。父接口里已经内置了save、findById、findAll、deleteById这些方法日常 CRUD 直接调用完全不用自己写实现。而 JPA 真正的好处不只是少写代码它自带实体状态管理比如你getOne之后修改些字段事务提交时它会自动发出update语句省掉你手动 update 的步骤。3.3 MyBatisSQL 精细控制派的代表如果你用过 MyBatis应该知道它的核心魅力是“SQL 你说写我来执行”。Spring Boot 里集成 MyBatis 需要引入第三方 starterdependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.2/version /dependency注意这个版本对应 Spring Boot 2.x如果工程是 Spring Boot 3.x则要选择 3.0.x 以上的版本。然后写 Mapper 接口Mapper public interface UserMapper { Select(select id, username, nickname from t_user where id #{id}) User findById(Long id); Insert(insert into t_user(username, nickname) values (#{username}, #{nickname})) int insert(User user); }或者用 XML 文件把 SQL 拆出去维护。MyBatis 的优势是动态 SQL 非常灵活比如复杂的多条件查询if、where、foreach处理起来很顺手劣势是实体和表之间的映射基本靠手写没有 JPA 那种自动建表能力。本地学习和毕设选型我更推荐 JdbcTemplate 或 JPA它们依赖少、上手快。3.4 三条路线怎么选直接给结论。如果项目就几张表、需求简单或者你只是想快速做个演示JdbcTemplate 最稳逻辑透明、排障容易。如果涉及实体关系比较复杂、想少写代码选 Spring Data JPA但要把ddl-auto和实体映射关系吃透否则线上环境一个update把表结构改了不是闹着玩。如果项目里 SQL 复杂、多表 join 多、需要动态 SQL那就 MyBatis本地练手时注意把 XML 路径配对。这个选择不用纠结太久因为 Spring Boot 的架构决定了你随时可以在同一个项目里混用。JdbcTemplate 能用、JPA 能用、MyBatis 也能用关键是把每个技术点背后的原理搞清楚而不是背框架名称。4. 手写一遍用户模块 CRUD从建表到接口调通4.1 建表 SQL 与实体映射这一章用一个最经典的“用户模块”把全链路串起来。先在 MySQL 里建表我建议手动建而不是靠 JPA 自动建因为手动建你才知道每列到底怎么定义。CREATE TABLE t_user ( id BIGINT NOT NULL AUTO_INCREMENT, username VARCHAR(50) NOT NULL, nickname VARCHAR(50) DEFAULT NULL, email VARCHAR(100) DEFAULT NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci;这里有两个细节。username必须加唯一索引否则代码里再怎么写幂等检查并发情况下还是可能插入重复数据唯一索引是数据库层面的最后一道防线。created_at和updated_at用CURRENT_TIMESTAMP自动填充时间比在 Java 代码里手动new Date()省心得多还不会有时区问题。对应的实体类Entity Table(name t_user) public class User { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; Column(nullable false, unique true, length 50) private String username; private String nickname; private String email; Column(name created_at, insertable false, updatable false) private LocalDateTime createdAt; Column(name updated_at, insertable false, updatable false) private LocalDateTime updatedAt; // 默认构造、getter、setter 省略实际开发中用 Lombok 的 Data 即可 }注意created_at、updated_at这两个字段我标记了insertable false, updatable false意思是插入和更新时让 JPA 不要管理这两个列完全交给数据库的DEFAULT CURRENT_TIMESTAMP处理。不然你保存实体的时候如果不手动 set这两个字段会插入 null和数据库默认值产生冲突。4.2 Repository、Service、Controller 三层代码先写 Repository。除了 JpaRepository 内置方法我加一个检查用户名是否存在的方法public interface UserRepository extends JpaRepositoryUser, Long { boolean existsByUsername(String username); OptionalUser findByUsername(String username); }Service 层的核心是业务规则和事务控制Service public class UserService { private final UserRepository userRepository; public UserService(UserRepository userRepository) { this.userRepository userRepository; } Transactional public User createUser(User user) { if (userRepository.existsByUsername(user.getUsername())) { throw new RuntimeException(用户名已存在); } return userRepository.save(user); } Transactional public User updateUser(Long id, User user) { User exist userRepository.findById(id) .orElseThrow(() - new RuntimeException(用户不存在)); exist.setNickname(user.getNickname()); exist.setEmail(user.getEmail()); return exist; } Transactional public void deleteUser(Long id) { userRepository.deleteById(id); } Transactional(readOnly true) public User getUserById(Long id) { return userRepository.findById(id) .orElseThrow(() - new RuntimeException(用户不存在)); } Transactional(readOnly true) public PageUser listUsers(Pageable pageable) { return userRepository.findAll(pageable); } }这里为什么事务注解都放在 Service 而不是 Controller因为 Controller 的职责只是接收请求和返回响应真正的业务操作应该发生在 Service 层。一个业务方法里可能连续做了多次数据库操作比如先查后改如果没有事务第二步失败时第一步已经提交数据就残了。Transactional保证了同一个方法里的所有数据库操作要么全成功要么全回滚。Controller 层就简单了RestController RequestMapping(/api/users) public class UserController { private final UserService userService; public UserController(UserService userService) { this.userService userService; } PostMapping public User create(RequestBody User user) { return userService.createUser(user); } GetMapping(/{id}) public User getById(PathVariable Long id) { return userService.getUserById(id); } GetMapping public PageUser list(RequestParam(defaultValue 0) int page, RequestParam(defaultValue 10) int size) { return userService.listUsers(PageRequest.of(page, size, Sort.by(id).descending())); } PutMapping(/{id}) public User update(PathVariable Long id, RequestBody User user) { return userService.updateUser(id, user); } DeleteMapping(/{id}) public void delete(PathVariable Long id) { userService.deleteUser(id); } }4.3 启动项目实际调一遍接口工程跑起来之后Spring Boot 默认端口是 8080我用 curl 做几个最简单的验证# 新增用户 curl -X POST http://localhost:8080/api/users \ -H Content-Type: application/json \ -d {username:zhangsan,nickname:张三,email:zhangsanexample.com} # 查询列表 curl http://localhost:8080/api/users?page0size5 # 根据 id 查询 curl http://localhost:8080/api/users/1第一次调通的时候心里会有一种“原来就这么回事”的感觉。实际上Spring Boot 的价值也正在这里你只需要把配置写对、对象模型理清剩下的请求路由、参数转换、JSON 序列化都已经处理好了。但别高兴太早本地环境最常见的问题集中在启动阶段的连接报错下面单独开一章专门排查。4.4 参数校验和事务回滚的补充上面代码里有个致命缺陷就是参数完全没有校验。如果前端传一个空 username你会直接往数据库里插运气好报DataIntegrityViolationException运气不好插入了脏数据。Spring Boot 自带的spring-boot-starter-validation可以方便地解决这个问题。在实体字段上打注解NotBlank(message 用户名不能为空) Size(max 50) private String username;Controller 参数前加Valid然后写个全局异常处理器把MethodArgumentNotValidException转成友好提示。这块在毕设里基本是加分项值得加上。事务回滚再看一个例子。比如注册用户时你既要插入用户表又要初始化一个统计记录两步必须同生共死Transactional public void register(User user) { userRepository.save(user); statisticRepository.initCounter(user.getId()); }如果statisticRepository.initCounter执行失败而userRepository.save已经提交你会发现用户表多了一个人统计表却没有记录。加上Transactional后Spring 会在第二个操作抛异常时把第一个操作回滚掉。除非你明确捕获了异常并把rollbackFor设置成特定异常否则默认只在 RuntimeException 时回滚这一点也值得记住。5. 本地运行高频报错排查SSL、socket、乱码一次说清5.1 启动时的连接失败和 socket 问题先说一个现象很多人在排查 Spring Boot 连不上 MySQL 时执着于看 Java 日志但真正的报错可能在 MySQL 客户端那一侧。比如最常见的ERROR 2002 (HY000): Cant connect to local MySQL server through socket /tmp/mysql.sock。这个报错不是 Spring Boot 抛的而是你直接在终端执行mysql命令时出现的原因是 MySQL 客户端默认通过 socket 文件和本机服务端通信而这个 socket 文件路径对不上或者服务根本没有起来。解决办法分两步。第一步确认服务在运行macOS 可以brew services start mysqlWindows 在服务管理器里看 MySQL 服务状态Linux 用systemctl status mysqld。第二步如果你图省事不想管理 socket连接串里直接用127.0.0.1代替localhost这样客户端会走 TCP 而不是 socket问题直接绕过去。Spring Boot 的 JDBC URL 里写127.0.0.1同样能达到这个效果这也是我在前面强调127.0.0.1的重要原因。5.2 Access denied 和用户授权问题项目启动后日志里出现Access denied for user demolocalhost (using password: YES)一般是两个原因。一个是密码真的写错了另一个是用户只能在特定主机登录。注意 MySQL 用户是“用户名 主机”绑定在一起的你创建用户时写的是demolocalhost那 JDBC 连接串里的 IP 是127.0.0.1时MySQL 会认为你是从localhost还是127.0.0.1来的这取决于 MySQL 的 host 匹配规则。如果你回头排查发现账号密码都正确但依然拒绝可以把用户的主机范围改一下CREATE USER demo% IDENTIFIED BY Demo123456; GRANT ALL PRIVILEGES ON demo_db.* TO demo%; FLUSH PRIVILEGES;%表示允许任何主机连接本地开发完全够用但生产环境不要这么干尤其不要给远程访问开放这个权限。5.3 中文乱码和 Incorrect string value 报错这个坑非常经典。Spring Boot 的日志里看到SQLException: Incorrect string value: \xE5\xBC\xA0...看起来是天书其实就是字符集没对齐。要么数据库或表不是utf8mb4要么 JDBC URL 里没带characterEncodingutf8。还有可能你连接的库没问题但表的字段是别的字符集。本地开发最稳妥的做法是三个地方全部对齐MySQL 服务端的character_set_server设为utf8mb4库和表建的时候显式用utf8mb4JDBC URL 里带characterEncodingutf8。注意这里写utf8就能满足连接器要求因为 JDBC 的 “utf8” 映射到 MySQL 服务端是完整的 4 字节字符集不会和 MySQL 自己的 utf8 混淆。如果你在数据库连接工具里看到的是乱码而不是异常那多半是客户端显示编码的问题换 Navicat 或 Workbench 的设置即可。5.4 端口冲突和驱动类不匹配Spring Boot 默认端口 8080 被占用时启动日志会直接报Port 8080 was already in use。这个最简单要么换个端口在application.yml里改server.port要么干掉占用进程。macOS 和 Linux 可以先用lsof -i :8080查出来是哪个进程Windows 用netstat -ano | findstr :8080再配合任务管理器结束。驱动类不匹配的问题则隐蔽一点。日志里能看到Loading class com.mysql.jdbc.Driver这种提示或者直接找不到驱动类。前面说过老项目是com.mysql.jdbc.Driver新版是com.mysql.cj.jdbc.Driver。如果你的项目明明引入了 MySQL 8 驱动配置里却写的旧类名运气好只是警告运气差直接报 ClassNotFoundException。这里我不建议去纠结哪个对直接把驱动类名写成com.mysql.cj.jdbc.Driver就完了。5.5 一个高性价比的排查套路把本地连 MySQL 的排查顺序整理成一个固定套路能节省大量时间。先从最简单的开始MySQL 服务有没有起来拿mysqladmin -uroot -p status或者SELECT 1验证。再验证 Spring Boot 配置的账号能不能手动登录用命令行执行mysql -h127.0.0.1 -udemo -p走一遍 TCP 连接能过说明网络层没问题。然后看 JDBC URL 的参数是否齐全特别是 SSL、时区、编码这三项。最后再看代码层面Spring Boot 项目有没有把事情搞复杂比如加了多数据源、分布式事务这类拎不清的配置。这套顺序本质上是把“数据库服务、网络、认证、驱动、业务代码”逐层脱开你不需要猜先确认最底层没问题再往上走。我见过太多人一报错就去看 Controller 代码结果数据库服务根本没启动白白浪费半小时。6. 我做本地开发时踩过的一些坑和最终建议要真说经验第一条就是把本地环境和生产环境分开看。本地连接 MySQL可以随便用useSSLfalse、allowPublicKeyRetrievaltrue可以账号密码简单点甚至可以容忍ddl-autoupdate自动改表结构但这些东西千万别原封不动搬上线。我吃过这个亏本地跑得好好的配置部署到服务器上之后一直报 SSL 连接失败排查半天才发现是服务器要求必须走安全通道而本地配置里把 SSL 关了。建议在项目里准备两套配置文件application-dev.yml和application-prod.yml本地用 dev部署用 prod切换的时候只改一个spring.profiles.active。第二条定期用命令行连一次库别完全依赖图形工具。Navicat、Workbench 这些工具确实方便但它们帮你隐藏了很多底层细节。等你哪天在无界面的服务器上部署项目连不了数据库可视工具连最基本的mysql -u都敲不利索的时候就很被动了。我在教程一开始就让你用终端验证不是装样子是想让你养成看原始日志、用命令行诊断的习惯。第三条小技巧给自己维护一个“本地连接配置速查表”。每次新建一个 Spring Boot 项目复制粘贴下面这段 URL 模板把库名和账号密码改掉就行不需要重新回忆参数是什么意思。jdbc:mysql://127.0.0.1:3306/你的库名?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8allowPublicKeyRetrievaltrue这句话能帮你避开至少三成的问题。最后再多说一句本地跑通只是第一步真正理解为什么配置是这样、报错意味着什么才是这几天折腾下来最值钱的收获。下次遇到 MySQL 相关的坑别怕按着从服务到网络再到驱动的顺序一层层剥问题永远有解。
返回列表