资讯动态

Java+MySQL+GUI图书管理系统:从JDBC到Swing的课设完整实战

发布时间:2026/10/1 5:35:09 来源:尧图企业网站定制
简介这是一份基于 JavaMySQL 实现的 GUI 图书管理系统课程设计资源覆盖管理员登录、图书管理、用户检索、借阅归还与图书查找等核心模块适合 Java 初学者、数据库课程设计学生及需要参考完整项目源码的开发者。压缩包共 187 个文件主要包含 48 个 Java 源码、64 个编译后的 class 文件、58 个 GUI 运行截图 png 图片以及 4 个 SQL 建库脚本、多份 docx/doc 说明文档和 md 笔记整体大小 16.25MB结构清晰便于按源码、脚本、文档分类查阅。已有 999 人学习下载。资源内含 Swing 界面设计与 JDBC 操作 MySQL 的完整实现可学习面向对象分层、增删改查 SQL 编写、借阅状态跟踪与管理员权限验证等关键知识点配套的数据库脚本和运行截图能帮助快速搭建环境并理解业务流程非常适合课程设计答辩或项目二次开发参考。1. 期末课设周里为什么这个“老掉牙”的 JavaMySQLGUI 组合还值得做期末课设周十个 Java 课程设计案例源码里至少五个是图书管理系统这组合看起来确实老。但把 JavaMySQLGUI 这三个词真正串起来——从 JDBC 连接串到 Swing 事件模型再到借还书的事务边界——你对 Java 数据库编程的基础理解会比背一百道 java 基础面试题都扎实。这个系统解决的事很具体图书信息录入、库存管理、借书还书登记、逾期状态查看。适合三类人正在做课程设计的学生、想用最小成本补 JDBC 和 Swing 基础的初学者、以及面试前想快速把一个 CRUD 项目整理成能讲清设计亮点的开发者。它不是什么高深架构但它是理解 Java 后端怎么跟数据库打交道的最短路径。2. 先把架子搭对技术选型、工程结构与图书表设计2.1 选型为什么是 Swing 而不是 JavaFX为什么不用 MyBatisSwing 看起来是老古董但它在 JDK 里原生存在只要有 JDK 就能编译运行这对课设环境非常友好。JavaFX 从 JDK 11 开始不再随 JDK 一起发布需要单独下载 SDK很多机房和线上环境装起来麻烦而且版本和 JDK 的匹配经常出玄学问题。你想想演示前一天发现 JavaFX 环境起不来那种翻车没人想经历。持久层这边常见做法是裸 JDBC PreparedStatement而不是 MyBatis。图书管理系统就是标准 CRUD数据量几百条MyBatis 的 XML 配置和 resultMap 映射对新手是一个黑匣子一旦查出来的字段对不上报错信息又长又难懂。裸 JDBC 虽然样板代码多但每一步都在你掌控里出问题能用打印 SQL 的方式直接定位。等你这套跑通了再去学 MyBatis 会发现无非是把这些样板代码换成了框架标签而已。数据库选 MySQL 是共识免费安装、教程多、机房环境默认就有。有一个细节在 MySQL 安装教程里经常被忽略那就是字符集一定要在安装时选成 utf8mb4而不是默认的 latin1否则后面中文乱码会让你排查到怀疑人生。GUI 框架也一样别用 IDEA 的图形界面拖拽插件去生成窗体那个生成的代码嵌套监听器报错信息根本读不懂手写 Swing 虽然慢一点但每一行都知道在干什么。2.2 表设计三张表还是五张表外键要不要加图书管理系统核心就三个实体用户、图书、借阅记录。很多课设会加还书表、罚款表、类别表但对一个图书管理系统来说三张表是底线五张表是加分项。我一般建议先做三张表跑通了再拆类别表。表设计直接决定后面 GUI 的代码量表拆得太细JTable 关联查询会让新手崩溃表太粗比如把借书和还书记录混在一张表里状态字段又会写得一团糟。外键这个事要单独说。课设题目一般要求外键约束所以我建议加但要知道代价加了外键之后删除图书或用户时必须先删干净引用它的借阅记录否则 MySQL 会报外键约束错误。这个约束在课设演示时反而是好事至少不会出现孤儿数据。另一个容易被扣分的是库存字段图书表里必须有总库存和可借库存两个字段可借库存默认值为 0这是 mysql 设置默认值为 0 的典型场景建表时直接写在 DEFAULT 里比每次插入都手动赋值靠谱。下面是建表脚本注意看字段类型和注释CREATE DATABASE IF NOT EXISTS library_system DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci; USE library_system; CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL COMMENT MD5 摘要不存明文, real_name VARCHAR(50) NOT NULL, role TINYINT NOT NULL DEFAULT 1 COMMENT 0-管理员 1-读者, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_book ( id INT PRIMARY KEY AUTO_INCREMENT, book_name VARCHAR(200) NOT NULL, author VARCHAR(100), publisher VARCHAR(100), isbn VARCHAR(20), total_stock INT NOT NULL DEFAULT 0, available_stock INT NOT NULL DEFAULT 0 COMMENT 可借库存减到 0 表示不可借, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, INDEX idx_book_name (book_name) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_borrow_record ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, book_id INT NOT NULL, borrow_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, due_time DATETIME NOT NULL, return_time DATETIME, status TINYINT NOT NULL DEFAULT 0 COMMENT 0-在借 1-已还, CONSTRAINT fk_borrow_user FOREIGN KEY (user_id) REFERENCES t_user(id), CONSTRAINT fk_borrow_book FOREIGN KEY (book_id) REFERENCES t_book(id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这个脚本里有三处值得讲。第一所有表都用 InnoDB 引擎因为 InnoDB 支持事务和外键MyISAM 虽然查询快但不支持事务借书扣库存这种操作没有事务就会出大问题。第二password 字段只存 MD5 摘要哪怕课设也要有这个习惯否则评审问一句“密码明文存的吗”就答不上来。第三t_book 的 book_name 加了普通索引后面 GUI 做模糊搜索时LIKE 查询能走索引数据量大了也不会卡。2.3 工程骨架Maven 目录与启动入口工程结构用 Maven 管理依赖这是现在 Javaweb 项目完整案例的标准姿势。不要用裸导入 jar 包的方式太容易漏依赖。Maven 结构的好处是 pom.xml 一写MySQL 驱动自动下载不用自己去官网找 jar 包。注意 mysql-connector-java 的坐标在 Maven 中央仓库里是真实存在的但版本号要跟你本机 MySQL 版本匹配MySQL 8 就用 8.0.x 的驱动别用 5.x 的旧驱动去连 MySQL 8。project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdcom.example/groupId artifactIdlibrary-system/artifactId version1.0-SNAPSHOT/version packagingjar/packaging properties maven.compiler.source8/maven.compiler.source maven.compiler.target8/maven.compiler.target /properties dependencies dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId version8.0.33/version scoperuntime/scope /dependency /dependencies /project这段 pom 里最关键的是 mysql-connector-j 的 scope 设为 runtime意思是编译时不依赖它运行时才需要。这样写的好处是代码里用 Class.forName 加载驱动时不会出现编译期报错而打包时驱动又会被带进去。如果你发现依赖下载不下来先检查 Maven 镜像源是不是默认的中央仓库被墙了换成阿里云镜像一般就能解决。目录结构上按 com.example.library 分包dao 包放数据库访问、ui 包放 Swing 界面、util 包放 JDBC 工具类和 MD5 工具类、entity 包放 User 和 Book 实体。启动入口就一个 Main.java里面 new 出登录窗口。3. 从零搭数据库建库脚本、JDBC 连接与连接池参数3.1 建库建表用 Workbench 导入脚本的三个常见问题建库脚本写好了下一步是把它跑起来。两种方式命令行 mysql -u root -p 进入后 source 执行或者用 MySQL Workbench 直接粘贴执行。mysql workbench 使用教程里最常用到的就是这个场景打开 SQL 编辑器把上面的脚本整个粘进去点执行按钮。但这一步有三个常见坑先给你排掉。第一个坑是执行顺序。如果脚本里有外键必须先建被引用的表t_user、t_book再建引用表t_borrow_record顺序反了会报外键关联失败。上面的脚本已经把顺序排好直接整段执行没问题。第二个坑是重复执行。第二次跑同一段脚本CREATE TABLE 不带 IF NOT EXISTS 会报表已存在所以我脚本里每个 CREATE TABLE 都带了 IF NOT EXISTS这是课设里最容易忽视的细节。第三个坑是字符集不一致。Workbench 默认连接字符集可能是 utf8但表是 utf8mb4查询结果里如果有 emoji 字符会乱码连接时在 Workbench 的 Connection 配置里把 Character Set 改成 utf8mb4 就行。表建完之后先用一句 SQL 验证一下顺便插入一条测试数据INSERT INTO t_user (username, password, real_name, role) VALUES (admin, MD5(123456), 系统管理员, 0); INSERT INTO t_book (book_name, author, publisher, isbn, total_stock, available_stock) VALUES (Java核心技术 卷I, 凯.S.霍斯特曼, 机械工业出版社, 9787111612711, 10, 10); SELECT * FROM t_user; SELECT * FROM t_book;这里的 MD5(123456) 是 MySQL 内置函数直接生成密码摘要这样后面 Java 端登录时也是把用户输入的密码做 MD5 再比对两端算法一致。插入图书时 total_stock 和 available_stock 都写成 10表示总库存 10 本、可借 10 本。验证查询用 SELECT * 就行课设阶段不用讲究字段列表。3.2 JDBC 连接工具类Class.forName 还需要吗URL 参数怎么配建好库和表接下来是 Java 端连数据库。JDBC 连接这一层我建议写一个独立的工具类把所有连接相关的配置集中管理。这个工具的写法在 JDK 8 和 JDK 11 下有个小差异JDK 8 里 Class.forName 加载驱动是必须的JDK 6 之后虽然 DriverManager 会自动加载 classpath 下的驱动 jar但显式写 Class.forName 能保证 classpath 扫描失败的场景也能加载。JDK 11 和更高版本里SPI 机制已经非常成熟这行代码可写可不写但写了不会报错建议保留因为这行代码在很多 java 基础面试题里都会被问到。package com.example.library.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class JdbcUtil { private static final String URL jdbc:mysql://127.0.0.1:3306/library_system ?useSSLfalse characterEncodingutf8 serverTimezoneAsia/Shanghai allowPublicKeyRetrievaltrue; private static final String USER root; private static final String PASSWORD 123456; static { try { Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }这段代码有四个参数必须解释清楚。useSSLfalse 是关掉 SSL 握手MySQL 8 默认开 SSL不关的话连接时会多一次握手性能差且容易报 SSL 相关的错。characterEncodingutf8 是告诉驱动用 UTF-8 编码传输不写这个中文插入数据库就是一堆问号。serverTimezoneAsia/Shanghai 解决 MySQL 8 的时区问题不写这个会报 CST 时区无法识别的错误。allowPublicKeyRetrievaltrue 配合 MySQL 8 默认的 caching_sha2_password 认证插件不写的话首次连接可能报公钥检索失败。这四个参数是 MySQL 8 环境下 JDBC 连接的标配一个都不能少。3.3 连接池还是裸连接参数怎么设不翻车课设规模下直接用 DriverManager 完全够但如果想让项目有点深度把连接池引进来是一个很好的加分项。连接池的作用是复用连接避免每次查数据库都新建一条 TCP 连接。图书管理系统的并发量不高但面试官问起连接池你要能说清楚参数。常见做法是用 HikariCP它是 Spring Boot 默认连接池轻量且性能好。参数建议值说明maximumPoolSize10池中最大连接数Swing 单机应用 10 足够minimumIdle2最小空闲连接低于这个值会补新连接connectionTimeout30000获取连接超时时间毫秒默认 30 秒idleTimeout600000空闲连接存活时间毫秒超过且大于 minimumIdle 则回收maxLifetime1800000连接最大生命周期毫秒防止数据库侧断开复用连接参数看起来多但对图书管理系统只需要关注 maximumPoolSize 和 connectionTimeout。池太小连续快速借书还书时会排队池太大空闲连接占内存。10 和 30000 是一组比较稳的搭配。注意 maxLifetime 一定要设MySQL 侧有 wait_timeout 默认 8 小时连接池里的连接长时间不用会被 MySQL 断开HikariCP 如果没有 maxLifetime拿到被断开的连接会报错。引入 HikariCP 只需在 pom.xml 加一个依赖然后把 JdbcUtil 里的 getConnection 改成从 HikariDataSource 获取即可。但这步是可选的如果你觉得课设时间紧直接保留 DriverManager 版本在第 6 章我再讲怎么在答辩时把连接池的事说成“预留的优化点”。4. 把 GUI 跑起来登录、图书列表与借还书的核心代码4.1 登录窗口密码校验和防注入的底线写法登录是 GUI 的入口也是第一个跟数据库打交道的窗口。这里的坑主要在两点一是密码传输用 JPasswordField 的 getPassword() 而不是 getText()前者返回 char[]用完之后可以手工置空降低内存被读取的风险二是查询语句必须用 PreparedStatement 拼参数不能把用户输入直接拼进 SQL 字符串那是 SQL 注入的经典入口。课设里用 Statement 拼串被评审问住的情况非常多。JButton loginBtn new JButton(登录); loginBtn.addActionListener(e - { String username usernameField.getText().trim(); String password new String(passwordField.getPassword()); if (username.isEmpty() || password.isEmpty()) { JOptionPane.showMessageDialog(loginFrame, 用户名和密码不能为空); return; } String sql SELECT id, real_name, role FROM t_user WHERE username ? AND password ?; try (Connection conn JdbcUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, Md5Util.md5(password)); try (ResultSet rs ps.executeQuery()) { if (rs.next()) { int id rs.getInt(id); String realName rs.getString(real_name); int role rs.getInt(role); loginFrame.dispose(); new MainFrame(id, realName, role).setVisible(true); } else { JOptionPane.showMessageDialog(loginFrame, 用户名或密码错误); } } } catch (SQLException ex) { ex.printStackTrace(); JOptionPane.showMessageDialog(loginFrame, 数据库连接失败请检查 MySQL 服务); } });这段代码的关键在 PreparedStatement。占位符 ? 由驱动转义后再发给 MySQL用户输入哪怕包含引号和分号也只会被当作普通字符串从根本上杜绝了拼接注入。Md5Util.md5() 是工具类方法把密码字符串转成 32 位十六进制摘要跟数据库里存的值比对。注意捕获 SQLException 后一定弹窗提示不能让用户点了登录按钮什么都没发生这是 Swing 程序体验感的底线。4.2 图书列表JTable 绑定 DefaultTableModel 的刷新机制登录进去之后的主界面核心是一个 JTable用来展示图书列表。这里最容易踩的坑是刷新问题查到的新数据不会自动出现在表格里必须手动操作数据模型。JTable 本身只负责画格子数据放在 DefaultTableModel 里所以刷新的正确姿势是清空 model 里的旧数据再逐行 addRow 新数据。private DefaultTableModel model new DefaultTableModel( new String[]{编号, 书名, 作者, 出版社, ISBN, 总库存, 可借}, 0); private JTable table new JTable(model); private void loadBooks(String keyword) { model.setRowCount(0); String sql SELECT id, book_name, author, publisher, isbn, total_stock, available_stock FROM t_book; if (keyword ! null !keyword.isEmpty()) { sql WHERE book_name LIKE ? OR author LIKE ?; } try (Connection conn JdbcUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { if (keyword ! null !keyword.isEmpty()) { String likePattern % keyword %; ps.setString(1, likePattern); ps.setString(2, likePattern); } try (ResultSet rs ps.executeQuery()) { while (rs.next()) { model.addRow(new Object[]{ rs.getInt(id), rs.getString(book_name), rs.getString(author), rs.getString(publisher), rs.getString(isbn), rs.getInt(total_stock), rs.getInt(available_stock) }); } } } catch (SQLException ex) { ex.printStackTrace(); } }这里 setRowCount(0) 是清空表格的关键不调用它每次查询结果都会追加在旧数据后面列表越查越长。模糊搜索用 LIKE 但值仍然通过占位符绑定防止有人输入 % 或 _ 通配符搞出奇怪的匹配。另一个细节是每次查询都新建 Connection 和 PreparedStatement用 try-with-resources 自动关闭这套写法是 java 基础里资源关闭的标准答案答辩时被问“连接什么时候关闭”就答这里。4.3 借书还书事务边界与条件更新rollback 是后悔药借书是整个系统里唯一需要多表联动的操作先扣图书库存再插入一条借阅记录。这两步任何一步失败都不能留下脏数据所以必须放在事务里。这里要强调一个关键点扣库存不能先 SELECT 查可用数再 UPDATE因为两个操作之间数据可能被别的用户改了。正确写法是直接用 UPDATE 语句加上 available_stock 0 条件让数据库自己判断这一步是原子操作。public boolean borrowBook(int userId, int bookId) { Connection conn null; try { conn JdbcUtil.getConnection(); conn.setAutoCommit(false); String updateSql UPDATE t_book SET available_stock available_stock - 1 WHERE id ? AND available_stock 0; try (PreparedStatement ps conn.prepareStatement(updateSql)) { ps.setInt(1, bookId); if (ps.executeUpdate() 0) { conn.rollback(); return false; } } String insertSql INSERT INTO t_borrow_record (user_id, book_id, due_time) VALUES (?, ?, ?); try (PreparedStatement ps conn.prepareStatement(insertSql)) { ps.setInt(1, userId); ps.setInt(2, bookId); ps.setTimestamp(3, Timestamp.valueOf(LocalDateTime.now().plusDays(30))); ps.executeUpdate(); } conn.commit(); return true; } catch (SQLException e) { if (conn ! null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); return false; } finally { if (conn ! null) { try { conn.setAutoCommit(true); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }这套代码有四个关键点。第一setAutoCommit(false) 之后后面所有 SQL 都在同一个事务里只有 commit() 才真正生效。第二UPDATE 的 WHERE 条件带 available_stock 0如果库存已经是 0这次更新影响 0 行马上 rollback 返回 false这就是后悔药——比先查再改安全得多。第三借阅记录的 due_time 用 LocalDateTime.now().plusDays(30) 表示默认借期 30 天。第四finally 里把 autoCommit 改回 true 再关闭连接是为了复用连接时不会把事务状态带出去。还书操作比借书简单只要事务里做两件事把库存加回来把借阅记录状态改成已还并写 return_time。同样需要事务。这段代码跟 borrowBook 结构一样把 UPDATE t_book SET available_stock available_stock 1 和 UPDATE t_borrow_record SET status 1, return_time NOW() 包在里面即可不再完整贴出你自己照着 borrowBook 的框架写一遍。5. 避坑排查乱码、Socket、事务与界面卡死的五个现场5.1 中文乱码插入的数据变成问号SELECT 出来也是问号现象是 GUI 里输入中文书名保存到数据库里变成 ???用 Workbench 看数据也是一堆问号。原因有三个按概率排序第一是建库时字符集用了 latin1第二是 JDBC 连接 URL 里少了 characterEncodingutf8第三是 IDE 控制台本身编码是 GBK。解决方法是先确认库表字符集SHOW CREATE TABLE t_book如果看到 CHARSETlatin1就用 ALTER TABLE 改成 utf8mb4然后再确认连接 URL 带 characterEncodingutf8。这两步做完基本解决如果还乱码把 IDE 的 File Encoding 和控制台编码都改成 UTF-8。这是 JDBC 开发里血泪经验排第一的问题。5.2 ERROR 2002 (HY000): Cant connect to local MySQL server through socket /tmp/mysql.sock现象是命令行连 MySQL 时报这个错或者在 Java 代码里连接 localhost 失败。原因是 MySQL 服务没启动或者 JDBC URL 里用了 localhost 导致驱动试图走 Unix socket。解决分两步先确认服务状态Windows 下在服务管理器里看 MySQL 是否启动Linux 下用 systemctl status mysql再把 JDBC 连接默认值里的 localhost 改成 127.0.0.1这样驱动会走 TCP 协议而不是 socket问题立刻消失。这个报错在 MySQL 安装教程里经常被提到原因是很多人装完 MySQL 忘记启动服务就直接跑 Java。5.3 借书成功但库存变负数或者订单记录存在但库存没扣现象是循环借同一本书可借库存变成 -1或者借阅记录里有一条数据但库存没变化。原因是忘开事务或者事务只包了其中一条 SQL另一种常见原因是 UPDATE 语句没带 available_stock 0 条件导致并发时把库存扣成负数。解决方法是把扣库存和插记录放进同一个事务setAutoCommit(false)、commit、rollback 缺一不可并且 UPDATE 的 WHERE 里加 available_stock 0。验证方法是连续借同一本书直到库存为 0再借一次应该返回“库存不足”而不是让库存变 -1。5.4 点登录按钮后整个窗口卡死转圈转十几秒才恢复现象是点击登录后窗口立即无响应鼠标变成转圈状态过一会才弹出主界面。原因是数据库查询是耗时操作但你把它直接写在了按钮的 ActionListener 里而 ActionListener 是在 Swing 的事件分发线程EDT上执行的耗时操作会把整个界面的重绘和事件处理都堵住。解决方法是把数据库查询放到另一个线程里执行然后用 SwingUtilities.invokeLater 把更新界面的代码切回 EDT。课设量小的话直接用 new Thread(() - loadBooks(keyword)).start() 就能解决面试被问深一点要说出 SwingWorker 才是标准方案。5.5 SQLNonTransientConnectionException: SSL connection error 或 Public Key Retrieval is not allowed现象是 Java 程序第一次连 MySQL 8 就报 SSL 连接错误或者报公钥检索不允许。原因是 MySQL 8 默认开启 SSL而且默认认证插件是 caching_sha2_password驱动版本不对或 URL 里没配 useSSL 和 allowPublicKeyRetrieval 就会报这两个错。解决方法是连接 URL 里加 useSSLfalse 和 allowPublicKeyRetrievaltrue同时把 mysql-connector-j 版本升到 8.0.x。还有一个隐藏坑是驱动类名MySQL 8 的驱动类名是 com.mysql.cj.jdbc.Driver老写法 com.mysql.jdbc.Driver 在新版本驱动里已经被移除了写错会直接报 ClassNotFoundException。6. 从课设到能演示数据校验、演示数据与演示话术6.1 输入校验和防注入的最后一道防线GUI 程序最容易在输入框上翻车。读者借书输入一个不存在的用户 ID或者 ISBN 里带引号程序直接崩了这在演示现场非常难看。我建议在每个输入框的监听器里加一层基础校验整数必须用 Integer.parseInt 且在 try-catch 里字符串长度用 length() 判断上限ISBN 格式用正则简单过滤。所有 SQL 统一走 PreparedStatement这条红线从登录贯穿到还书不拼任何字符串。6.2 演示数据让评审一眼看懂业务流程写一段初始化数据的 SQL提前插入 3 个测试用户一个管理员、两个读者和 10 本经典书覆盖不同出版社和库存状态。重点演一本书库存只有 1 本借出去之后再借第二次界面弹出“库存不足”的提示这个场景最能证明事务和库存逻辑是真实有效的。演示前先跑一遍业务确保当天不会翻车。6.3 演示话术与验证方法把表和数据状态讲成故事我习惯的演示顺序是先打开 Workbench 展示三张表和初始数据再进系统登录管理员账号搜索一本书借出后立刻切到 Workbench 看这本书的 available_stock 减了 1借阅记录表多了一行。这个“数据库实时变化”的对比一出来比讲十页架构图都管用。最后还书再切过去看库存加回来整套闭环就成立了。这个习惯我从第一次课设用到现在每回演示完评审都不怎么追问细节了。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑