尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
MySQL手把手教程:安装配置、CRUD操作与JavaWeb员工项目实战
1. 整个系列怎么规划第01篇要解决什么MySQL 大概是这个星球上用得最广的开源关系型数据库没有之一。小到个人博客大到电商后台、物流系统、BI报表一堆业务系统底层都是它扛着。这个系列取名叫“手把手教你MySQL”第一篇我先把地基打牢从安装、配置、基础操作一路干到第一个能跑起来的完整项目。为什么把“完整项目”作为第一篇的终点我见过太多人装完MySQL之后只会执行几个SELECT 1、show databases然后就没有然后了。学数据库不跟实际业务挂钩等于背了满脑子语法规律但一个场景套不进去。所以这一篇宁可步子迈大一点直接用一个小而完整的 JavaWeb 员工管理系统把建库、建表、写SQL、用JDBC连库、增删改查全部串一遍。整个过程走完你手里就有了一个能运行、能演示、能拿去扩展成课程设计的真项目。这个系列的内容我按一个新手最自然的成长路径来排的第01篇本篇安装 MySQL 8.0做基础配置完成建库建表与CRUD最后用 JDBC 跑通第一个小项目。后续篇事务与隔离级别、索引与查询优化、存储过程与触发器、数据备份恢复、主从复制以及用 Spring Boot MyBatis 重构今天这个小项目。学习环境方面我建议 Windows 作为主力开发机有条件的话再准备一台 Linux 服务器或者虚拟机做对照实验。原因很简单日常开发在 Windows 上最顺手可真实生产环境几乎都是 Linux两边都熟悉才不容易被环境差异卡住。关于版本选型默认装 8.0.x。8.0 从 2018 年发布到现在已经足够成熟窗口函数、CTE、原子DDL、更好用的优化器这些都比老版本强太多而且是当前主流云数据库的默认底座版本。如果你因为历史项目被迫用 5.7本篇安装思路同样适用只是部分参数名有差异我在关键位置会标注出来。2. 环境准备与安装实操Windows 和 Linux 两条路都踩一遍2.1 Windows 安装 MySQL 8.0MSI安装包方式Windows 上最省事的方式是直接用 MySQL Installer。去 MySQL 官网的 Downloads 页面选 MySQL Community Server 8.0.x 对应的 Windows (x86, 32-bit), MSI Installer 版本。注意区分安装器体积大小web版只有几 MB安装时联网下载组件完整版接近四百 MB离线环境必须选这个。安装时记得选Server only那些 MySQL for Visual Studio、MySQL Workbench 之类的组件后面需要再补第一遍尽量保持干净减少干扰项。安装路径建议不要带中文和空格比如D:\MySQL\Server\8.0避免后面写配置文件和命令行操作时出现编码或转义问题。进入配置环节有几个坑我展开说端口号默认3306如果本机已经装了旧版 MySQL 或者纳管数据库先netstat -ano | findstr 3306查一下端口是不是被占用。被占用就改成 3307后面所有连接串都要同步改。Authentication Method 选择Use Legacy Authentication还是Use Strong Password Encryption8.0 默认推荐后者加密方式是caching_sha2_password。但如果你后面要接的客户端、驱动版本比较老比如 5.x 的 JDBC 驱动有可能连不上。新手阶段我建议直接选 Strong Password 即可配合 8.0.x 新版驱动没有问题如果连不上再把 root 的插件改成 mysql_native_password。Root 密码务必记住这是你这台机器数据库的最高权限。大小写、数字、特殊符号都要有后面项目连接也要用这个密码。密码忘了很麻烦毕竟要跳过权限表、改配置重启才能重置。配置完成后可以在 Windows 服务列表里看到MySQL80这个服务默认开机自启。命令行验证一下mysql -uroot -p输入密码后能进入mysql提示符说明安装成功。2.2 Windows 安装另一种思路ZIP 压缩包方式MSI 安装器虽然傻瓜但有时候会莫名卡在 “MySQL Installer” 的配置步骤上或者你想把 MySQL 做成绿色版跟着项目走。这种情况我推荐用 ZIP 包手搭。下载mysql-8.0.x-winx64.zip解压到D:\MySQL\Server\8.0。然后在根目录新建my.ini至少包含这些关键内容[mysqld] basedirD:/MySQL/Server/8.0 datadirD:/MySQL/Server/8.0/data port3306 character-set-serverutf8mb4 collation-serverutf8mb4_unicode_ci default-authentication-plugincaching_sha2_password [client] default-character-setutf8mb4注意 datadir 这个目录通常不会自动创建你需要手动建一个空的data文件夹或者让初始化命令帮你建。接着以管理员身份打开命令提示符进入 bin 目录执行初始化mysqld --initialize-insecure--initialize-insecure会生成一个密码为空的 root 账户适合第一次登录后手动改密如果你用--initialize它会在日志文件里生成随机临时密码找起来麻烦新手不太推荐。初始化完成后安装系统服务mysqld --install MySQL80 net start MySQL80然后登录改密码mysql -uroot --skip-password ALTER USER rootlocalhost IDENTIFIED BY 你的新密码; FLUSH PRIVILEGES;这种方式的好处是整个过程每一步都看得见出问题也好定位而且对后面理解 MySQL 的目录结构非常有帮助。我个人在教学时更倾向于先带大家走一遍这种方式。2.3 LinuxCentOS / Ubuntu安装 MySQL 8.0生产环境基本都在 Linux所以 Linux 安装至少要走一遍。CentOS / RHEL 系先装官方 yum 源再安装wget https://dev.mysql.com/get/mysql80-community-release-el7-9.noarch.rpm rpm -ivh mysql80-community-release-el7-9.noarch.rpm yum install mysql-community-server -y systemctl start mysqld systemctl enable mysqld安装完成后MySQL 8.0 的随机临时密码会自动写进日志文件grep temporary password /var/log/mysqld.log拿到临时密码后登录并改密mysql -uroot -p ALTER USER rootlocalhost IDENTIFIED BY 新密码;Ubuntu/Debian 系更简单apt update apt install mysql-server-8.0 -y systemctl start mysqlDebian 系安装时默认 root 是 auth_socket 认证也就是说在系统命令行里直接用sudo mysql就能免密进去要改成密码登录需要手动切换到 mysql_native_password 或 caching_sha2_password。新手阶段如果喜欢用客户端工具连建议执行一下切换ALTER USER rootlocalhost IDENTIFIED WITH caching_sha2_password BY 你的密码;2.4 安装后的基线检查无论哪种方式装完都建议花三分钟做下面的检查SELECT VERSION(); -- 版本号 SHOW VARIABLES LIKE port; -- 端口 SHOW VARIABLES LIKE character_set_server; -- 服务端字符集 SHOW VARIABLES LIKE lower_case_table_names; -- 表名大小写策略我用这组命令排查过不少环境问题。比如字符集如果还是 latin1后面插入中文直接乱码lower_case_table_names在 Windows 上是 1不区分大小写、Linux 上是 0区分大小写这直接决定你项目里写表名时要不要统一大小写。建议项目里全部小写表名谁写谁知道省多少事。注意lower_case_table_names在 8.0 里只有初始化时能改装完再改不生效所以一定要在初始化前想清楚。Linux 默认 0如果你就是要 Windows 和 Linux 两套环境跑同一个项目建议初始化时加上--lower-case-table-names1。3. 数据库基础建库建表与 CRUD 实操3.1 root 权限太大先建一个普通用户上来就用 root 操作业务库是非常不好的习惯。root 的权限是整个 MySQL 实例一旦误删了系统表后果很难收拾。我们在项目开始前先创建专用账号CREATE USER app_userlocalhost IDENTIFIED BY App_User_123; CREATE USER app_user% IDENTIFIED BY App_User_123; GRANT ALL PRIVILEGES ON employee_db.* TO app_userlocalhost; GRANT ALL PRIVILEGES ON employee_db.* TO app_user%; FLUSH PRIVILEGES;注意app_user%和app_userlocalhost是两个独立账号%表示允许从任意主机连接适合远程调试localhost 用于本机连接。两个都建的好处是让你彻底理解 MySQL 的“账号用户名主机”模型。3.2 建库建表用员工表把字段类型讲明白我们这个项目是一套极简员工信息管理系统Employee Management System简称 EMS数据库名employee_db。以员工表为主表同时设计一张部门表两张表之间用外键关联既简单又能把常见关系表设计带出来CREATE DATABASE IF NOT EXISTS employee_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE employee_db; CREATE TABLE department ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT 部门ID, dept_name VARCHAR(50) NOT NULL UNIQUE COMMENT 部门名称, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间 ) ENGINEInnoDB; CREATE TABLE employee ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT 员工ID, emp_no VARCHAR(20) NOT NULL UNIQUE COMMENT 工号, emp_name VARCHAR(50) NOT NULL COMMENT 姓名, gender TINYINT DEFAULT 1 COMMENT 1-男 0-女, salary DECIMAL(10,2) DEFAULT 0.00 COMMENT 薪资, dept_id INT NOT NULL COMMENT 所属部门ID, hire_date DATE COMMENT 入职日期, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, CONSTRAINT fk_dept FOREIGN KEY (dept_id) REFERENCES department(id) ) ENGINEInnoDB;这里每个字段选择都有讲究emp_no用 VARCHAR 而不是 INT因为工号往往带前缀或补零纯数字类型会把000123变成123。gender用 TINYINT 存 0/1比直接存汉字节省空间而且代码层面好判断。salary必须用 DECIMAL不能用 FLOAT/DOUBLE。浮点数存金额会出精度问题这是做财务系统的经典教训。hire_date用 DATE 类型只关注年月日如果还要存具体时分秒就换 DATETIME。引擎统一指定 InnoDB因为它支持事务、外键、行级锁是现阶段最稳妥的选择。外键约束我建了是为了让新手理解表关联但等后面讲性能优化的时候我们会讨论为什么生产环境有时要刻意去掉外键。3.3 最常用的 CRUD 语句一条条过往部门表插数据INSERT INTO department (dept_name) VALUES (技术部), (产品部), (人事部);往员工表插数据INSERT INTO employee (emp_no, emp_name, gender, salary, dept_id, hire_date) VALUES (A0001, 张伟, 1, 15000.00, 1, 2022-03-15), (A0002, 李娜, 0, 13000.00, 2, 2022-06-01), (A0003, 王强, 1, 9000.00, 3, 2023-01-10);查询最核心的一条 SQL把员工表和部门表关联起来SELECT e.emp_no, e.emp_name, e.gender, e.salary, d.dept_name, e.hire_date FROM employee e INNER JOIN department d ON e.dept_id d.id WHERE e.salary 10000 ORDER BY e.salary DESC;这条语句几乎涵盖了单表多表查询的全部基础知识点别名、关联条件、过滤条件、排序。能一眼看懂说明前面的 JOIN 概念基本过关。更新和删除UPDATE employee SET salary 16000.00 WHERE emp_no A0001; DELETE FROM employee WHERE emp_no A0003;注意 UPDATE 和 DELETE 一定要带 WHERE。忘了带条件的后果就是全表被改、全表被删。我见过不止一次新手在测试库里UPDATE employee SET salary 0然后整脸懵的场景。如果不小心发生了赶紧看有没有开事务或者备份否则只能祈祷。3.4 让 MySQL 自动管理时间上面两张表里都有create_time字段默认值设为CURRENT_TIMESTAMP这样插入数据时不用手动传时间MySQL 会自动记录。员工表的hire_date是业务字段必须手动传入因为它代表“入职日期”这样一个有业务含义的时间点不能用系统当前时间替代。这个区分是初学者最容易混淆的地方系统字段与业务字段要分开不能偷懒全用当前时间。4. 第一个完整项目实操JavaWeb JDBC 员工管理系统4.1 为什么第一个项目选 JavaWeb JDBC很多人会问现在写后端不是都用 Spring Boot MyBatis 吗为什么第一个项目反而用一个看起来“老掉牙”的组合我的答案是正因为 JDBC 是底层它能把数据库连接怎么建立、SQL 怎么执行、结果集怎么映射讲得明明白白。用 Spring Boot 的时候这些东西全被框架封装了你只会写 Mapper 接口出了个数据库连接问题根本不知道怎么排查。JDBC 相当于让你亲手把数据传输管道接一遍等你知道这条管道长什么样了再用 MyBatis 不过是把“管道工”换成“自动管道机”。这个项目我会保留最底层的连接管理逻辑用纯 Servlet JSP JDBC 实现学完这个再去看 Spring Boot你会觉得很多东西似曾相识。4.2 项目结构准备环境要求JDK 8 及以上、Tomcat 9、MySQL 8.0、IDEA 社区版或专业版都可。项目用 Maven 管理依赖核心只需要一个依赖dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId version8.0.33/version /dependency这个mysql-connector-j就是 8.0 系列里替换老mysql-connector-java的新坐标驱动类是com.mysql.cj.jdbc.Driver。如果你用旧坐标依赖也能解析但建议直接用新名字。项目目录结构如下employee-web/ ├── pom.xml ├── src/main/java/com/example/ems/ │ ├── util/DBUtil.java │ ├── dao/EmployeeDao.java │ ├── model/Employee.java │ └── servlet/EmployeeServlet.java ├── src/main/resources/db.properties └── src/main/webapp/ ├── WEB-INF/web.xml ├── list.jsp └── add.jsp4.3 数据库连接工具类配置外置与连接复用JDBC 的第一步是获取连接。最蠢但也最常见的写法是每执行一次 SQL 就DriverManager.getConnection()一次用完就关。这种方式在本地测试没问题但并发一上来就会把数据库连接数打满。我们先用连接池的思路简化实现但保留DBUtil作为统一入口后面可以平滑替换成 Druid 或 HikariCP。db.properties放在 resources 目录下jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/employee_db?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8 jdbc.usernameapp_user jdbc.passwordApp_User_123注意 URL 里三个参数useSSLfalse本地开发不需要 SSL 加密走明文即可加上这个参数免得 8.0 连本地时弹出 SSL 告警。serverTimezoneAsia/Shanghai8.0 驱动对时区敏感不指定会报The server time zone value Öйú±ê׼ʱ¼ä is unrecognized这类时区乱码错误。characterEncodingutf8让驱动和数据库之间的传输字符集统一为 UTF-8避免中文乱码。DBUtil类的写法package com.example.ems.util; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; public class DBUtil { private static String url; private static String username; private static String password; static { try (InputStream in DBUtil.class.getClassLoader().getResourceAsStream(db.properties)) { Properties props new Properties(); props.load(in); Class.forName(props.getProperty(jdbc.driver)); url props.getProperty(jdbc.url); username props.getProperty(jdbc.username); password props.getProperty(jdbc.password); } catch (Exception e) { throw new ExceptionInInitializerError(数据库配置初始化失败 e.getMessage()); } } public static Connection getConnection() throws Exception { return DriverManager.getConnection(url, username, password); } }这里有几个容易踩的坑Class.forName()在 8.0 驱动里其实可以省略因为 JDBC 4.0 以上采用 SPI 机制自动注册驱动。但我仍然写了因为老项目迁移时多这一行能少很多莫名其妙的“No suitable driver found”问题。配置加载用类加载器读取 classpath 资源不要用绝对路径否则换环境就崩。静态块里初始化失败要尽早抛异常不要让项目启动后带着一个坏连接池运行。4.4 JDBC 增删改查PreparedStatement 是底线写 JDBC 时永远用PreparedStatement不要用Statement字符串拼接 SQL。原因有两个预编译可以防 SQL 注入还方便处理参数类型。下面是EmployeeDao的核心方法package com.example.ems.dao; import com.example.ems.model.Employee; import com.example.ems.util.DBUtil; import java.sql.*; import java.util.ArrayList; import java.util.List; public class EmployeeDao { public ListEmployee findAll() { ListEmployee list new ArrayList(); String sql SELECT e.id, e.emp_no, e.emp_name, e.gender, e.salary, e.hire_date, d.dept_name FROM employee e INNER JOIN department d ON e.dept_id d.id ORDER BY e.id; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { while (rs.next()) { Employee emp new Employee(); emp.setId(rs.getInt(id)); emp.setEmpNo(rs.getString(emp_no)); emp.setEmpName(rs.getString(emp_name)); emp.setGender(rs.getInt(gender)); emp.setSalary(rs.getBigDecimal(salary)); emp.setHireDate(rs.getDate(hire_date)); emp.setDeptName(rs.getString(dept_name)); list.add(emp); } } catch (Exception e) { e.printStackTrace(); } return list; } public int insert(Employee emp) { String sql INSERT INTO employee (emp_no, emp_name, gender, salary, dept_id, hire_date) VALUES (?,?,?,?,?,?); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, emp.getEmpNo()); ps.setString(2, emp.getEmpName()); ps.setInt(3, emp.getGender()); ps.setBigDecimal(4, emp.getSalary()); ps.setInt(5, emp.getDeptId()); ps.setDate(6, new java.sql.Date(emp.getHireDate().getTime())); return ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); return 0; } } public int deleteById(int id) { String sql DELETE FROM employee WHERE id?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setInt(1, id); return ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); return 0; } } }这里我用了 try-with-resourcesConnection、PreparedStatement、ResultSet 自动关闭比 finally 块里手动 close 干净得多。注意rs.getDate返回的是java.sql.Date如果要转java.util.Date直接赋值给Date类型属性即可JDBC 驱动内部做了转换。4.5 Servlet 控制层把 HTTP 请求转换成业务动作Servlet 这部分其实不复杂它就是接收前端请求调用 DAO 层处理数据再根据操作结果跳转页面。核心的“查询全部员工列表”请求处理如下package com.example.ems.servlet; import com.example.ems.dao.EmployeeDao; import com.example.ems.model.Employee; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException; import java.util.List; WebServlet(/employee) public class EmployeeServlet extends HttpServlet { private EmployeeDao dao new EmployeeDao(); Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String action req.getParameter(action); if (delete.equals(action)) { int id Integer.parseInt(req.getParameter(id)); dao.deleteById(id); } ListEmployee list dao.findAll(); req.setAttribute(employees, list); req.getRequestDispatcher(/list.jsp).forward(req, resp); } Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); Employee emp new Employee(); emp.setEmpNo(req.getParameter(empNo)); emp.setEmpName(req.getParameter(empName)); emp.setGender(Integer.parseInt(req.getParameter(gender))); emp.setSalary(new java.math.BigDecimal(req.getParameter(salary))); emp.setDeptId(Integer.parseInt(req.getParameter(deptId))); emp.setHireDate(java.sql.Date.valueOf(req.getParameter(hireDate))); dao.insert(emp); resp.sendRedirect(employee); } }一个细节req.setCharacterEncoding(UTF-8)必须写在读取任何参数之前否则 POST 请求里的中文名称会乱码。GET 请求的参数编码在 Tomcat 9 里默认已经处理好了但 POST 不会这是 JavaWeb 老生常谈的坑。4.6 前端展示用 JSP 把结果渲染出来list.jsp要做的事情很简单从 request 作用域里取出员工列表用 JSTL 渲染成表格。核心片段% page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % html body h2员工列表/h2 table border1 cellpadding8 cellspacing0 tr th工号/thth姓名/thth性别/thth薪资/thth部门/thth入职日期/thth操作/th /tr c:forEach items${employees} varemp tr td${emp.empNo}/td td${emp.empName}/td td${emp.gender 1 ? 男 : 女}/td td${emp.salary}/td td${emp.deptName}/td td${emp.hireDate}/td tda hrefemployee?actiondeleteid${emp.id} onclickreturn confirm(确定删除)删除/a/td /tr /c:forEach /table br/ a hrefadd.jsp新增员工/a /body /htmladd.jsp里表单的actionemployee、methodpost这样和后端doPost对应起来。到这里项目的请求链路已经完整浏览器发起请求 → Tomcat 根据WebServlet(/employee)找到 Servlet → Servlet 调 DAO → DAO 通过 JDBC 操作 MySQL → 数据返回给 Servlet 存到 request → forward 到 JSP → 渲染 HTML 返回浏览器。4.7 把项目完整跑起来在 IDEA 里配置 Tomcat把项目打成 war 包部署启动 Tomcat浏览器访问http://localhost:8080/employee就能看到员工列表。再走一遍新增流程页面上能查到刚插入的数据这个项目就算完整跑通了。跑通之后我强烈建议你亲手做一次“端到端追踪”在findAll()方法里打一个断点浏览器刷新页面看请求怎么进入 Servlet、SQL 怎么执行、结果集怎么封装这比看一百遍教程都管用。我自己带新人的时候这一步是最能帮助人建立全局感的。5. 安装配置与项目联调常见问题排查5.1 表结构没问题why 中文乱码八成是字符集问题。先执行SHOW VARIABLES LIKE character_set_%;重点看character_set_server和character_set_database。如果都是 utf8mb4再检查 JDBC URL 有没有加characterEncodingutf8以及页面contentType有没有写charsetUTF-8。乱码问题通常出在这三层中的某一层逐层排查即可。5.2 root 密码忘了Windows 上以管理员身份停掉 MySQL 服务然后在 my.ini 里加一行skip-grant-tables重启服务后免密登录mysql -uroot进去后先给 root 设新密码ALTER USER rootlocalhost IDENTIFIED BY 新密码; FLUSH PRIVILEGES;设置完成后改回配置文件去掉skip-grant-tables重启服务。注意这个操作期间任何程序都能免密连库必须在局域网或本机操作搞完马上恢复。5.3 连接时报 Access denied for user如果是Access denied for user app_userlocalhost优先检查密码是否正确如果确认密码对那就检查账号的主机限制。用 root 登录后执行SELECT user, host FROM mysql.user WHERE userapp_user;如果你只有app_user%的记录本地连接时 MySQL 会尝试用app_userlocalhost匹配匹配不上就拒绝。所以本地跟远程两个账号到底建没建齐一查便知。5.4 服务起不来 / 端口冲突net start MySQL80报错先看data目录下的.err日志文件这个文件里写的错误信息通常是最直接的。如果端口冲突则netstat -ano | findstr 3306看谁占着端口改端口或停掉占用进程。5.5 JDBC 驱动报 ClassNotFound / No suitable driver绝大多数情况是依赖没下载成功或作用域不对。Maven 工程里检查target/classes下有没有驱动 jar再看看pom.xml里面依赖的 scope 是否意外写成了provided或test。还有个小概率是 IDEA 缓存问题执行mvn clean后再 reimport 一次。5.6 建表报主键冲突id 不是自增吗把建表语句里的id INT AUTO_INCREMENT PRIMARY KEY与原表对照看一下。如果原表建的时候没有 AUTO_INCREMENT后面再ALTER TABLE employee MODIFY id INT AUTO_INCREMENT;补上即可。另外 DELETE 清空表后想重置自增计数用TRUNCATE TABLE employee;而不是DELETE FROM employee;前者会把自增序列一并重置。6. 这一篇的实操心得与下一步建议装 MySQL 本身不难难的是装完之后你知不知道自己在装什么、怎么验证、怎么把它用起来。这一篇走完你手里应该有四个成果一台装了 MySQL 8.0 的机器、一套建好的员工库表、一份能跑通的基础 CRUD 技能、一个能演示给同学看的 JavaWeb 项目。把这四样东西握在手里后面再学索引、事务、优化都会有着陆点而不是悬在空中的概念。最后分享两个我在实操中发现的小技巧。第一个是关于排查问题的思路数据库报错时先看异常信息的前三行绝大多数同学会直接滑到最后找Caused by但真正有用的错误提示往往就在最开始。先读异常头部能省下大量时间。第二个是关于学习节奏MySQL 的知识点又杂又多不要指望一遍全记住我在带人时常说“先做后懂”先把今天这个项目原样跑通哪怕PreparedStatement的内部原理暂时理解不透先用熟悉的手感等你写烂了再回头抠原理一切都豁然开朗。下一篇我会带着大家把 JDBC 连接用连接池重构再顺手把这套员工系统里埋的几个数据冗余和查询低效问题挨个拆掉顺便引出索引和事务这两个重头戏。先把今天这篇的每一步复现一遍下一篇我们继续。
RELATED

相关推荐

数据库性能优化实战:从慢查询定位到索引与架构设计

数据库性能优化实战:从慢查询定位到索引与架构设计

数据库慢,这事几乎每个团队都遇到过。我见过太多这样的场景:一张两千万行的订单表,业务方说“就是查一个订单号,怎么要三秒多”,开发试着加了个索引,没效果,于是把问题抛给DBA;DBA看…

📅 2026/10/7 3:47:07
软考中级软件设计师上午题高频考点精华:数据结构、查找与排序

软考中级软件设计师上午题高频考点精华:数据结构、查找与排序

简介:一份面向软考软件设计师(中级)考生的核心考点笔记,精编自考试高频内容,适合考前快速建立知识框架并针对薄弱环节强化记忆。笔记系统展开数据结构、树结构、查找与排序四大模块,覆盖邻接矩阵、顺序/链式…

📅 2026/10/7 3:47:07
Harmonist 安全防御实战:4类提示注入扫描如何让恶意AI智能体现形

Harmonist 安全防御实战:4类提示注入扫描如何让恶意AI智能体现形

Harmonist 安全防御实战:4类提示注入扫描如何让恶意AI智能体现形 【免费下载链接】harmonist Portable AI agent orchestration with mechanical protocol enforcement. 186 agents, zero runtime dependencies. 项目地址: https://gitcode.com/gh_mirrors/ha/har…

📅 2026/10/7 3:47:07
MORE NEWS

更多资讯

📰

MiniMax M Plan 迁移与 H3 视频本地部署:Claude Code 和 Cursor 接入实录

1. 从 Token Plan 到 M Plan:这次改动到底动了谁的蛋糕如果你最近两个月一直在用 MiniMax 的 API 做多模态应用,大概率已经被那条“Token Plan 即将下线”的公告刷过屏。我自己的几个小项目从去年开始就挂在 Token Plan 上,视频生成、语音合成…

📰

基于Python的高校学业预警系统设计与实现:Flask+MySQL实战指南

简介:面向高校计算机相关专业毕业生的基于Python的高校学生学业预警系统毕业设计资源包已整理上传,系统采用Django框架与MySQL数据库实现,包含学生管理、成绩管理、预警分析等核心功能模块,并配套完整毕业论文文档,适合…

📰

JSP火车票查询系统实战:Servlet+JDBC+MySQL从环境搭建到答辩避坑

简介:一套面向Java Web初学者的JSP火车查询系统毕业设计项目,采用B/S模式,以Java、JSP与MySQL为核心技术栈,适用于计算机专业学生进行课程设计、毕业设计或Java Web入门练习。资源包含完整项目源代码、数据库脚本及部署配置&#…

📰

t3code:基于Electron的终端增强型开发壳工具解析

1. 项目概述:t3code 是什么?它解决的不是“安装问题”,而是开发者本地环境的“认知摩擦”t3code 这个名字乍看像某个开源工具的代号,但结合当前全网搜索热度——t3code、CLI、Electron、Homebrew、winget 这些词高频共现&#xff…

📰

Python递归实战:朱梁真理元嵌套函数与闭包避坑指南

如果你也被“递归”这两个字折磨过,那这篇内容应该能帮到你。我最近在复盘一个困扰团队很久的 Python 递归问题,最后把所有经验浓缩成了一条内部黑话,全称叫“朱梁真理递归元嵌套函数定理”。名字听着中二,其实就是我们对“递归 …

📰

AI Native团队落地手册:CLAUDE.md、Plan Mode与Agent实战

1. 从“用AI写代码”到“AI Native团队”的认知跃迁这两年我参与过不少团队的研发流程改造,从最早大家偷偷用补全插件,到后来公司统一采购助手账号,再到现在张口闭口“AI Native”,中间踩的坑比想象中多得多。很多人以为把Copilot…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬