零基础学Java与MySQL:从JDBC到连接池与事务的完整入门指南
后台开发这行当聊到技术栈几乎绕不开 Java 和 MySQL 这对组合。我这两年被问得最多的问题之一就是零基础学 Java到底怎么入门——每次我都会回一句别光啃语法把 MySQL 连起来做东西才算真正入门。这篇算是我的经验整理从 JDK 和 MySQL 的安装配置开始一路讲到 JDBC 怎么写、为什么要有连接池、事务是什么、面试问什么覆盖了从零基础到能独立写一个小 CRUD 项目的完整链路。已经会一点 Java 的朋友可以直接跳到 JDBC 和连接池那几章完全没接触过的建议从头开始慢慢过。无论哪种情况文章里提到的坑和解决思路都是我在实际环境里反复踩过的照着做能少走很多弯路。1. 先想清楚为什么要从 Java MySQL 这两个开始1.1 你的第一个完整项目为什么需要数据库我教过不少零基础的朋友他们最开始写程序都是这种节奏用 System.out.println 打印一个Hello World然后写几个 if-else用变量存点数据用数组模拟一下列表跑通了觉得自己会编程了。这些练习当然没问题但有一个致命短板——程序一关数据全没了。你想想你写一个学生成绩管理系统在程序里往 List 里 add 几条记录看起来能查能改一切正常但有一天你重启程序发现录入的成绩全部消失了。这种时候你才会意识到一个完整的系统一定得有一个能长期保存数据、并且支持多个人一起访问的组件。这就是数据库存在的意义。而 MySQL 作为目前应用最广的开源关系型数据库和 Java 这门使用量常年排名靠前的后端语言自然就成了最经典的入门组合。从实际就业和项目落地的角度看Java 后端项目里 MySQL 出现的频率极高。招聘需求里写熟悉 Java熟悉 MySQL是最低配的要求。可以说只学 Java 不学 MySQL就像只学了开车但不知道加油站怎么找跑不了远路。反过来只学 MySQL 不学 Java也会发现很难把数据库能力真正落地到业务里。两个一起学形成业务逻辑由 Java 写、数据存储和查询交给 MySQL的心智模型后续无论是学框架 Spring Boot、MyBatis还是接触 Redis 这些缓存组件思维框架都不会散。1.2 入门阶段的知识地图学到什么程度算入门经常有人问JavaMySQL 入门到底要学多少东西我给一个可量化的标准满足这几条你就算真正入门了Java 基础语法变量、数据类型、流程控制、数组、方法。面向对象类、对象、继承、多态、接口、异常处理。Java 常用类String、集合框架ArrayList、HashMap 至少要会用。MySQL 基础建库建表、数据类型、增删改查SELECT/INSERT/UPDATE/DELETE、条件查询、排序ORDER BY、分组聚合GROUP BY、COUNT、SUM。JDBC能通过 Java 程序连接到 MySQL完成增删改查。基本工程意识能封装一个自己的数据库工具类理解资源关闭、异常处理知道连接池是什么、为什么需要。我见过太多人一上来就去啃 Spring Boot、微服务结果连 JDBC 都没写过遇到问题根本不知道底层发生了什么。入门阶段慢就是快。上面这张地图普通人每天投入两三个小时一个半月到两个月时间是足够的。学完这些你至少能独立写一个命令行版本的学生管理或者图书借阅这样的小系统这在后续做项目时是非常重要的底气。2. 环境搭建全流程JDK、MySQL 和 IDEA附三个高频报错2.1 JDK安装与环境变量配置JDK 版本选择这件事网上吵了不知道多少年。我的建议是初学者直接上 JDK 17这是目前最稳妥的 LTS 长期支持版本语法特性和大部分企业现状接轨。不用纠结是不是应该先学 JDK 8JDK 8 已经是快二十年前的东西了你学 17 照样能看懂老代码反过来不一定成立。下载时别去乱七八糟的网站Oracle 官网或者 Adoptium 的 Temurin 发行版都可以。国内网络环境下下载慢可以找国内镜像源但一定要确认是官方镜像。Windows 安装很简单下载 exe 安装包一路 Next记住安装路径例如 C:\Program Files\Java\jdk-17。装完之后环境变量是最容易出问题的一步。右键此电脑→属性→高级系统设置→环境变量新建一个 JAVA_HOME值填你的 JDK 安装路径然后在系统变量 Path 里新增一条 %JAVA_HOME%\bin。打开命令行输入 java -version 和 javac -version两个命令都能输出版本号说明装好了。这里有个细节很多老教程会让你配置 CLASSPATH写着.;%JAVA_HOME%\lib\dt.jar;...。如果你用的是 JDK 9 以上的版本这一步可以直接跳过。JDK 9 开始模块化之后默认会加载当前目录下的类手动设置 CLASSPATH 反而可能引发奇怪的问题。我见过有人照着十几年前的博客配了一通最后 java 命令反而报错。macOS 和 Linux 的思路一样把 JAVA_HOME 和 PATH 写进 shell 配置文件~/.zshrc 或 ~/.bashrc。macOS 上即使你用了 brew 安装的 JDK我也建议手动 export 一下 JAVA_HOME否则后面 Maven、IDEA 经常会找不到 JDK 路径。2.2 MySQL 8.0的下载、安装与初始化MySQL 版本选择也很明确新学直接用 8.0.x 社区版Community Server。5.7 已经停止维护网上搜到的 5.7 教程越来越少没必要开局就用一个接近淘汰的版本。下载地址是 MySQL 官网的 Community Server 页面Windows 选 MSI 安装包macOS 选 dmgLinux 直接用系统包管理器安装最省事。Windows 上 MSI 安装过程有几个重点安装类型选 Server Only初学不需要装一堆 Application端口保持默认 3306认证方式直接选Use Strong Password Encryption这是 8.0 的默认方案 caching_sha2_password设置好 root 密码后记得选择把 MySQL 注册成 Windows 服务开机自启省得每次手动启动。Linux 下稍微要注意一点不同发行版的初始化流程不太一样。Ubuntu 用 apt install mysql-server 装好后root 默认可能没有密码直接 sudo mysql 就能进CentOS 系用 yum 安装后会在日志里生成一个临时密码需要先 grep 出来再登录修改grep temporary password /var/log/mysqld.log mysql -u root -p ALTER USER rootlocalhost IDENTIFIED BY 你的新密码; FLUSH PRIVILEGES;装好 MySQL 之后第一件事建议立刻建一个自己的库和表练一下基础 DDLCREATE DATABASE test DEFAULT CHARACTER SET utf8mb4; USE test; CREATE TABLE user ( id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, age INT DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这个示例里包含了三个非常基础但重要的知识点AUTO_INCREMENT 自增主键、DEFAULT 0 这种字段默认值写法、以及字符集为什么用 utf8mb4 而不是 utf8。MySQL 里的 utf8 其实是 3 字节的 utf8mb3存不了 emoji 和部分生僻字从 8.0 开始官方都推荐使用 utf8mb4这是实战中很多人踩过的坑。如果你想用图形化工具管理数据库推荐两个DBeaver免费且跨平台和 MySQL Workbench官方出品。IDEA 自带 Database 工具面板也能连 MySQL但初学阶段我更建议多用命令行敲 SQL命令敲熟了图形工具就只是辅助。2.3 三个入门必踩的坑error 2002、端口占用、源发行版17警告坑一ERROR 2002 (HY000): Cant connect to local MySQL server through socket /tmp/mysql.sock这个报错在 Linux 和 macOS 上非常常见搜索量常年排在前列。核心含义是MySQL 客户端试图通过 Unix socket 连接本地 MySQL 服务但没有连上。绝大多数情况下原因就两个服务没启动或者 socket 路径不对。排查链路我建议按顺序走确认服务状态systemctl status mysqlUbuntu 系或 service mysql status。如果服务没启动先启动systemctl start mysql 或 service mysql start。启动后还是报错看日志/var/log/mysql/error.log 或 /var/log/mysqld.log。检查 socket 文件是否存在ls -l /var/run/mysqld/mysqld.sock如果文件不存在说明 MySQL 根本没有正常启动。实在不行绕过 socket强制走 TCP 连接测试mysql -h 127.0.0.1 -P 3306 -u root -p。如果这样能连上那就是客户端默认 socket 路径和服务端配置的路径不一致去 my.cnf 里找 socket 配置改一下即可。很多人会困惑我明明启动了 MySQL为什么还报这个错——因为你用命令行的 default 方式连接时MySQL 客户端默认走 socket不走 TCP。socket 文件没生成或者路径不对就会 2002。理解了这一层这个报错就不可怕了。坑二端口 3306 被占用MySQL 启动失败或者能启动但外部工具连不上大概率是端口冲突。常见于电脑之前装过旧版 MySQL、或者装了其他占用 3306 的应用。Windows 排查命令是netstat -ano | findstr 3306输出里最后一列是 PID然后去任务管理器找到对应进程结束或者用 taskkill /F /PID 编号 强杀。Linux 下用lsof -i:3306 # 或者 netstat -tunlp | grep 3306如果确认是残留的旧 MySQL 进程占着端口千万不能直接杀先把旧服务停掉再改配置或者卸载干净。还有一种思路是改 MySQL 监听端口在 my.ini 或 my.cnf 里把 port 改成 3307但初学阶段不建议动端口改了之后所有连接、工具配置都要跟着改容易把自己绕晕。坑三Java 编译警告源发行版 17 需要目标发行版 17这个警告在 IDEA Maven 项目里出现概率极高。本质是代码的 source 版本是 17但编译 target 版本设置的不是 17Java 编译器认为前后不一致于是给出警告。导致的问题通常是项目运行时报 UnsupportedClassVersionError 或者编译失败。解决思路IDEA 里按 CtrlAltShiftS 打开 Project Structure确认 Project SDK 选择了 JDK 17Modules 里 Language level 也对应设置。Settings → Build, Execution, Deployment → Compiler → Java Compiler把 Target bytecode version 改成 17或与 SDK 一致。如果项目是 Maven 项目检查 pom.xml 里是否配置了 maven-compiler-plugin或者 properties 中是否声明了编译版本properties maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler.target /properties改完之后一定记得在 IDEA 的 Maven 面板点一下刷新重新导入依赖再重新编译。这个坑的深层原因是项目模板创建时的默认版本和当前 JDK 不一致。以后你进公司接手老项目大概率也会遇到版本不匹配的问题提前把排查链路掌握好是很值的。3. JDBC 上手从连接字符串到 CRUD 完整代码3.1 JDBC 到底在 JDK 和 MySQL 之间扮演什么角色很多初学者一上来就学 MyBatis最后连 JDBC 都没写过。但说句实在话MyBatis 底层包装的就是 JDBC。你要是不知道 JDBC 那几十行代码长什么样框架出个错你都看不懂堆栈更别说理解框架帮我们节省了什么。JDBCJava DataBase Connectivity是 JDK 提供的一套数据库访问接口。你不需要知道 MySQL 的传输协议是怎么设计的只要按照 JDBC 的规范写代码再引入一个驱动包就能操作数据库。打个比方JDBC 是电脑上的 USB 接口标准MySQL 驱动就是你要插上去的那个设备。没有标准各家数据库各说各话有了标准Java 程序面对 MySQL、Oracle、PostgreSQL 都是同一套写法。MySQL 的 Java 驱动现在的 Maven 坐标是 mysql-connector-j8.0 版本驱动类名是 com.mysql.cj.jdbc.Driver。如果你在旧教程里看到 com.mysql.jdbc.Driver那是 5.x 时代的驱动虽然 8.0 还兼容但新项目不推荐这么写。3.2 六步完成一次数据库操作代码逐行拆解一个标准的 JDBC 查询流程如下每一步我标了注释String url jdbc:mysql://localhost:3306/test?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8allowPublicKeyRetrievaltrue; String user root; String password 你设置的密码; // 1. 加载驱动8.0 其实可以省略但建议保留帮助理解机制 Class.forName(com.mysql.cj.jdbc.Driver); // 2. 建立连接 Connection conn DriverManager.getConnection(url, user, password); // 3. 创建语句 Statement stmt conn.createStatement(); // 4. 执行SQL String sql SELECT id, name, age FROM user; ResultSet rs stmt.executeQuery(sql); // 5. 处理结果集 while (rs.next()) { int id rs.getInt(id); String name rs.getString(name); int age rs.getInt(age); System.out.println(id - name - age); } // 6. 关闭资源后开先关 rs.close(); stmt.close(); conn.close();看似简单但有几个关键细节必须讲透。首先是 URL 里的参数它们不是随便写的useSSLfalse本地开发不需要加密连接8.0 默认反而会输出警告。serverTimezoneAsia/Shanghai必须设置不然时间字段读写会乱成差 8 小时。characterEncodingutf8防止中文乱码。allowPublicKeyRetrievaltrue使用 caching_sha2_password 认证方式时如果客户端没有缓存服务端公钥会报Public Key Retrieval is not allowed加上这个参数才能正常连接。第二个细节是资源关闭。连接、语句、结果集这三个资源都实现了 AutoCloseable一定要关闭。初学最容易犯的错是只关了 ConnectionStatement 和 ResultSet 不关或者没放在 finally 里程序一出异常连接就泄漏了。更推荐用 try-with-resources 写法JVM 会在 try 块结束时自动关闭try (Connection conn DriverManager.getConnection(url, user, password); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { while (rs.next()) { // 处理结果 } } // 自动关闭3.3 PreparedStatement 为什么是标准答案我见过新手用 Statement 拼接 SQL比如这样String name 张三; stmt.executeQuery(SELECT * FROM user WHERE name name );这样能跑但隐患巨大。假如 name 的值是 OR 11拼出来的 SQL 变成了SELECT * FROM user WHERE name OR 11这个条件恒为真等于把整张表都查出来了。这就是最经典的 SQL 注入攻击。而 PreparedStatement 用占位符 ? 预先把 SQL 结构发送给 MySQL之后设置参数时驱动会帮你转义特殊字符从根上避免拼接问题String sql SELECT * FROM user WHERE name ?; PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, name); ResultSet rs ps.executeQuery();除了安全PreparedStatement 还有性能优势。对于同一条 SQL 反复执行比如循环插入批量数据MySQL 会复用预编译的执行计划而不是每次都重新解析 SQL。批量插入时配合 addBatch 和 executeBatch 效率更高String sql INSERT INTO user(name, age) VALUES(?, ?); PreparedStatement ps conn.prepareStatement(sql); for (int i 0; i 100; i) { ps.setString(1, user i); ps.setInt(2, i); ps.addBatch(); } ps.executeBatch();写到这里我强烈建议你把 PreparedStatement 当成唯一选择。面试问 SQL 注入怎么防标准答案就是参数化查询不是去写什么过滤关键字。3.4 封装一个简单的 DBUtil在实际项目中不可能每个方法都写一遍注册驱动、获取连接、关闭资源的代码。入门阶段就可以自己封装一个工具类这也是后面所有数据库操作的底座public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/test?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8allowPublicKeyRetrievaltrue; private static final String USER root; private static final String PASSWORD 你的密码; static { try { Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(ResultSet rs, Statement stmt, Connection conn) { if (rs ! null) { try { rs.close(); } catch (SQLException ignored) {} } if (stmt ! null) { try { stmt.close(); } catch (SQLException ignored) {} } if (conn ! null) { try { conn.close(); } catch (SQLException ignored) {} } } }这个类看着朴素但写 CRUD 时非常顺手。等学到 MyBatis 你会发现框架底层也是围绕连接管理、语句处理、结果映射这几个概念在做统一封装。4. 写业务代码前的关键一课连接池和数据一致性4.1 裸 JDBC 的短板与连接池的救场如果你用上面的 DBUtil 连数据库跑一个小 Demo 完全没问题但一旦放到真正的 Web 项目里问题立刻暴露每一次请求都创建一次物理连接用完再关闭。创建连接是什么代价要经历 TCP 三次握手、MySQL 认证、会话初始化这一通操作可能消耗几百毫秒比执行一条简单 SQL 还慢。并发一高几十个请求同时来每个都现拉连接数据库直接被拖垮。解决办法就是连接池。连接池在内存里维护一批创建好的连接用的时候从池里借用完还回去不关闭物理连接。这跟线程池是一个道理——池化是后端开发最重要的思维之一。入门阶段不用自己实现直接用成熟组件。Java 世界里常见的连接池有 HikariCP、Druid、C3P0简单对比一下连接池特点适用场景HikariCP性能极好Spring Boot 默认内置新项目首选轻量高效Druid阿里开源功能全自带监控页面国内企业常用监控需求多C3P0老牌框架配置繁琐维护老项目才会遇到HikariCP 的用法非常简洁dependency groupIdcom.zaxxer/groupId artifactIdHikariCP/artifactId version4.0.3/version /dependencyHikariConfig config new HikariConfig(); config.setJdbcUrl(jdbc:mysql://localhost:3306/test?useSSLfalseserverTimezoneAsia/Shanghai); config.setUsername(root); config.setPassword(你的密码); config.setMaximumPoolSize(10); config.setMinimumIdle(5); config.setConnectionTimeout(30000); HikariDataSource dataSource new HikariDataSource(config);之后每次要连接try (Connection conn dataSource.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { // ... }注意这里的 close() 并不是真的关闭连接而是把连接归还给连接池。这个语义差异很重要也是很多新手困惑的地方。4.2 用事务保证数据一致性的代码姿势连接池解决了性能问题数据一致性则涉及另一个核心技术事务。举最经典的转账例子从 A 账户扣 1000给 B 账户加 1000。这两步必须同时成功或者同时失败不能发生钱扣了但对方没收到或者钱没扣对方却收到了这种状态。MySQL 的 InnoDB 引擎是支持事务的。JDBC 里默认是每次执行 SQL 自动提交autocommittrue也就是说上面两条 SQL 如果不做特殊处理天然就分开了。想组合成事务要这样写Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); String sql1 UPDATE account SET balance balance - 1000 WHERE user_id 1; String sql2 UPDATE account SET balance balance 1000 WHERE user_id 2; try (PreparedStatement ps1 conn.prepareStatement(sql1); PreparedStatement ps2 conn.prepareStatement(sql2)) { ps1.executeUpdate(); ps2.executeUpdate(); } conn.commit(); } catch (Exception e) { if (conn ! null) { conn.rollback(); } throw e; } finally { if (conn ! null) { conn.close(); } }核心就是 setAutoCommit(false)手动控制 commit 和 rollback。一旦第二条 SQL 执行失败程序走 catch 块回滚数据库回到事务开始前的状态。这就是 ACID 里面的原子性和一致性在代码层面的落地。这里有一个隐蔽的坑如果连接是从连接池里拿的事务结束之后没有把 autoCommit 重置回 true下一次从池里拿到同一根连接的人会意外继承一个不自动提交的会话导致明明 executeUpdate 了却不生效。所以用连接池加手写事务时最好在 finally 里把 conn.setAutoCommit(true) 恢复回来或者直接交给 Spring 的 Transactional 托管。MySQL 默认的事务隔离级别是可重复读REPEATABLE READ。这个级别下同一事务里多次查询同一条数据结果一致不会读到其他事务未提交的数据。但要注意可重复读级别下理论上可能出现幻读MySQL 通过 next-key lock 解决了大部分幻读问题细节值得后续深入学习。4.3 面试怎么答如何保证数据一致性数据一致性是面试最爱问的方向深度可以一直延伸到分布式。入门阶段先把单库事务答明白就行。我的回答思路是这样分三层的第一层有事务兜底。解释 ACID说明开启方式——Spring 里 Transactional 注解或者裸 JDBC 的 setAutoCommit(false)。强调事务保证多个操作要么全部成功、要么全部回滚。第二层锁和并发控制。如果两个用户同时改同一行数据事务只能保证流程正确不能保证不相互覆盖。这时候要用悲观锁也就是 SELECT ... FOR UPDATE让其他事务等行锁或者乐观锁设计一个 version 字段更新时检查 version 是否变化变化就重试或者报冲突。这两种思路是并发场景下最常被问到的也是后面做秒杀、库存扣减的核心。第三层分布式一致性。当涉及多库、多服务时本地事务不够用了。常见方案有两阶段提交2PC、本地消息表、MQ 最终一致性、Seata 分布式事务框架。这块属于进阶内容对应届生来说能说出方案名字并且讲清楚核心思路已经是明显的加分项不需要真的实现过。5. 从入门到面对面试高频考点和学习路线5.1 索引、事务、SQL优化最值得花时间的三个方向MySQL 面试高频方向排第一的是索引。你要能回答出来MySQL InnoDB 的索引底层为什么是 B 树。等值查询哈希更快所以不用哈希红黑树是二叉平衡树数据量大时树太高磁盘 IO 次数多。B 树是矮胖结构叶子节点用链表串起来天然适合范围扫描和排序。面试官问到这里大概就能判断你是在背答案还是真懂。创建一个索引很简单CREATE INDEX idx_user_name ON user(name);但更要紧的是理解最左前缀原则。比如你建了组合索引 (name, age)查询条件只有 age 时索引是用不上的。这条是最容易被问到也是最容易被忽略的。另一个实战方向是慢查询和 EXPLAIN。线上业务卡顿第一步通常是开慢查询日志把执行时间超过阈值的 SQL 抓出来SET GLOBAL slow_query_log ON; SET GLOBAL long_query_time 1;然后对慢 SQL 执行 EXPLAIN 看执行计划EXPLAIN SELECT * FROM user WHERE age 30;重点看 type 字段的取值const 最好ref 不错range 可以接受ALL 是灾难。一旦出现 ALL 全表扫描优先考虑加索引。很多新人不会主动用 explain这个习惯建议从入门阶段就养成后面排查问题会省很多时间。存储过程、排序ORDER BY、UPDATE 语法也都是热搜词里高频出现的。存储过程现在日常开发中用得越来越少更多是在旧系统里维护面试偶尔会问知道基本语法和适用场景即可。ORDER BY 排序看起来简单但要理解排序是有代价的——如果 order by 的字段没有索引MySQL 可能需要建立临时文件做排序数据量大时性能会明显下降。5.2 JavaMySQL 学习路线入门、进阶、项目实战三个阶段刷再多的题都不如完整写过一个项目。我建议把学习路线分成三个阶段每个阶段都要有可运行的东西输出阶段时间建议核心内容阶段产出第一阶段4~6周Java 基础语法、面向对象、集合、MySQL 建库建表、SQL 增删改查能独立写出带条件、排序、分组的 SQL第二阶段2~3周JDBC、异常处理、资源管理、事务基础命令行版学生成绩管理或图书管理系统第三阶段4~6周Spring Boot、MyBatis、RESTful 接口、统一参数校验一个可运行的 Web 项目博客系统或简易商城第一阶段不用我多说跟着教程把 Java 语法和 SQL 基础过一遍重点是每天都要写代码。第二阶段最容易被忽略但恰恰是最关键的过渡。用 JDBC 完成一个完整的命令行版管理系统需要你来我往地处理增删改查。做完这个项目你再学 MyBatis很多东西就是顺的Mapper 就是 SQL 的映射SqlSession 底层就是连接管理你只是在换一种更高效的方式写你已经会的东西。第三阶段开始接触 Spring Boot。这个阶段的重心是理解 Web 请求是怎么进来的、Controller 怎么写、Service 和 Mapper 的分层有什么用、事务注解加在哪儿。项目跑起来之后再回头优化 SQL、加索引、看执行计划性能优化的意识也是这样一点点培养起来的。再提醒一句不要陷入八股文的泥潭。面试题可以背但要建立在理解的基础上。最好的方式就是拿自己写过的项目去解释概念——比如你做过图书管理系统就能很自然地讲清楚事务解决了我什么实际痛点、为什么查询变慢了以后我加了索引就快了很多。这些真实经历比一百句标准答案都管用。最后关于 Java 学习还有一点建议遇到问题优先看错误信息原文别急着复制粘贴去搜索引擎或者问 AI。比如 error 2002 这种报错关键词已经告诉你连不上 socket 了顺着服务状态和路径排查一遍你的排错能力会提升得很快。我见过不少工作了几年的人遇到报错第一反应还是复制粘贴这样永远学不会排查问题的思路。就写到这吧。希望这篇分享能帮你把 Java MySQL 的入门之路走顺环境配好、代码跑通、项目做出来的时候你会觉得前面这些折腾都是值的。