资讯详情

Java课设超市管理系统:从表结构到JDBC事务的完整实战

📅 2026/10/1 12:03:52 | 华诺云谱 👁 阅读
Java课设超市管理系统:从表结构到JDBC事务的完整实战
简介面向Java课程设计场景的超市管理系统源码包以命令行方式模拟后台进销存与销售记录管理核心功能围绕商品、库存、数据库读写展开适合作Java基础、JDBC与MySQL开发的学习练手项目。压缩包共49个文件包含22个class编译文件、22个java源文件、1个sql数据库脚本、1个mysql-connector-java-5.1.18-bin.jar驱动及工程配置文件整体约783KB目录按control/dao/po/db/view/main分层便于对照源码理解业务逻辑与分层思想。资源已有1379人学习下载适合课设参考或复习数据库编程。内容覆盖JDBC连接、SQL增删改查、异常处理、多线程等要点并包含完整的建库脚本与驱动依赖拿到后可结合自身数据库环境导入工程快速运行和二次修改。1. 超市管理系统这个课设比增删改查多一步事务才是拿高分的关键每年答辩季我都能在教室后排看到同一幕学生演示收银员登录、扫码、结账动作行云流水老师点了一下头然后问出那句经典问题——刚才结算的时候如果订单明细写失败了但库存已经被扣了系统会变成什么样教室瞬间安静。这不是学生不努力而是大多数课设把精力全花在界面上业务层和数据库层是脱节的。超市管理系统是 Java 课程设计里最长青的一题本质是一个最小的进销存系统角色权限、商品档案、入库、销售、库存扣减、流水查询每一个功能都在逼你把 Java 基础、JDBC 和 SQL 串成一条完整的数据流。这篇文章按 Swing MySQL JDBC 这套最稳妥的课设组合来拆覆盖从表设计到事务处理、从环境搭建到答辩验证的完整路径。适合刚学完 Java 基础、正在为课设头秃的人也适合想用最短时间把项目边界搞清楚的准毕业生。2. 从需求到表结构把超市管理系统拆成角色、页面和四张表课程设计最常见的翻车方式是打开 IDE 就开始写登录窗口写到一半发现缺这缺那最后把全班的表结构抄来抄去。我的习惯是反过来先拿一张纸回答三个问题——谁会用这个系统他在哪个界面干什么这件事会改动哪几张表这三个问题回答完需求其实就已经拆完了。2.1 先拆角色收银员、仓库管理员、经理分别操作什么超市管理系统不是给一个人用的。最小可用版本里至少有三个角色收银员、仓库管理员、经理。收银员坐在收银台前扫码、结算、打印小票他需要快速找到商品但不能随便改价格仓库管理员负责商品入库和库存盘点他关心的是进价、数量和入库时间经理不碰具体业务他要看的是销售总额、库存积压和低库存预警。这三个角色对应三个操作面权限模型不用做得很复杂。我一般会在 t_user 表里放一个 role 字段界面加载时根据当前登录用户的角色决定显示哪些菜单、启用哪些按钮数据库层不额外做拦截。实战里有一个容易忽略的细节收银员登录后虽然能看见商品管理菜单但应禁用修改价格和删除商品按钮否则验收时老师随手点一下发现收银员能改价格系统完整性就垮了。角色、操作和数据权限的关系可以先用一张表定下来角色核心操作对应界面数据权限收银员扫码、结算、打印小票收银台读商品、写销售单仓库管理员入库、盘点、调库存入库管理读写商品与入库单经理查销售报表、查库存预警统计报表只读所有数据这张表直接对应到代码里的菜单权限判断也对应到后面你要给答辩老师讲的权限控制这个知识点。不要为了追求高级去引入 Shiro 或 Spring Security课设阶段讲清楚按角色控制界面可见性就够了老师想听到的是设计思路不是框架名词。2.2 四张核心表的设计商品、入库、销售、用户角色拆完之后你会发现所有业务最后都落在几张表上用户表 t_user、商品表 t_product、入库单 t_stock_in、销售单 t_sale 和销售明细 t_sale_item。严格说是五张表但 t_sale_item 是 t_sale 的子表通常可以按四张核心表 一张明细表理解。先说设计原则。商品表 t_product 上有一个 stock 字段它存的是当前库存量是一个冗余字段入库和销售产生的流水分别放在 t_stock_in 和 t_sale_item 里。为什么不直接从流水表汇总出库存因为每次查询都做 SUM 会非常慢课设数据量小无所谓但你要能跟老师解释清楚冗余是为了读性能。一个完整的建库脚本长这样CREATE DATABASE supermarket_db CHARACTER SET utf8mb4; USE supermarket_db; -- 用户表区分管理员/收银员的角色入口 CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(30) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL, role VARCHAR(10) NOT NULL DEFAULT cashier ) ENGINEInnoDB; -- 商品表stock 为冗余库存min_stock 用于预警 CREATE TABLE t_product ( id INT PRIMARY KEY AUTO_INCREMENT, barcode VARCHAR(32) NOT NULL UNIQUE, name VARCHAR(50) NOT NULL, spec VARCHAR(30), unit VARCHAR(10), price DECIMAL(10,2) NOT NULL, stock INT NOT NULL DEFAULT 0, min_stock INT NOT NULL DEFAULT 10 ) ENGINEInnoDB; -- 入库单只记录入库流水 CREATE TABLE t_stock_in ( id INT PRIMARY KEY AUTO_INCREMENT, product_id INT NOT NULL, quantity INT NOT NULL, in_price DECIMAL(10,2) NOT NULL, operator_id INT NOT NULL, create_time DATETIME NOT NULL ) ENGINEInnoDB; -- 销售主单一次结算生成一条 CREATE TABLE t_sale ( id INT PRIMARY KEY AUTO_INCREMENT, total_amount DECIMAL(10,2) NOT NULL, cashier_id INT NOT NULL, create_time DATETIME NOT NULL ) ENGINEInnoDB; -- 销售明细一条主单对应多行商品 CREATE TABLE t_sale_item ( id INT PRIMARY KEY AUTO_INCREMENT, sale_id INT NOT NULL, product_id INT NOT NULL, price DECIMAL(10,2) NOT NULL, quantity INT NOT NULL, subtotal DECIMAL(10,2) NOT NULL ) ENGINEInnoDB;几个必须讲清楚的参数选择。第一数据库和连接串统一用 utf8mb4不要用 utf8因为 utf8 在 MySQL 里存不了部分生僻字和特殊符号用 utf8mb4 可以少一个乱码翻车点。第二金额字段用 DECIMAL(10,2)不要用 float 或 double浮点数的二进制表示会导致 0.10.2 不等于 0.3这个知识点在 Java 基础面试题里也是高频考点用在表设计上会让你给老师的印象分高不少。第三建表没有写物理外键只用代码逻辑保证关联关系。原因是课设阶段导数据、删数据特别频繁物理外键会挡住很多本来没问题的操作比如你要清空 t_sale 重测一次如果有外键就得先删 t_sale_item顺序颠倒就报错。逻辑外键配合事务控制完全够用这也是很多生产系统的保守做法。2.3 技术选型为什么课设默认用 Swing MySQL JDBC打开任何 Java 课程设计案例源码包围绕超市管理系统最常见的组合就三种Swing MySQL、JSP Servlet MySQL、Spring Boot Vue或 Thymeleaf。我的建议是如果课设没有明确要求 Web 化优先选 Swing MySQL JDBC。原因很现实。课设验收的核心是能跑 能讲。Swing 程序双击跑起来不需要配置 Tomcat不依赖网络端口老师的机器上只要装了 JDK 和 MySQL 就能演示环境兼容性是三种方案里最高的。JDBC 是 Java 连接数据库的底层方式所有代码都在你手里PreparedStatement、ResultSet、事务这些知识点全是 Java 基础课程里讲过的内容答辩时你能说清楚每一步而不是把系统当成黑匣子。JavaWeb 方案多出来的 Servlet、JSP 或 Spring 容器概念如果不熟悉反而容易在你项目里的 bean 是怎么装配的这类追问下兜不住。话虽如此如果课程要求里明确写了基于 Web或使用 SSM那 Swing 方案就别交了。此时替换思路是把界面层换成 JSP/Servlet 或 Spring Boot 的 ControllerDBHelper 和 DAO 层代码可以原样搬过去事务逻辑也不变。也就是说下面要讲的 DAO、事务、SQL 设计在换成 Web 技术栈后依然成立这才是这坨代码里真正值钱的部分。3. 跑通最小骨架建库、DBHelper、登录功能一条龙进入代码部分。很多学生在环境上浪费的时间比写代码还多这一章按照着做就能跑起来的顺序来。3.1 先定环境版本再去动手常见做法是 JDK 8 或 11 MySQL 5.7 或 8.0 mysql-connector-java 5.1.49 或 8.0.x。这里有一条血泪经验尽量用 MySQL 8.0 配套 8.0.x 的驱动 jar如果是拿去老师机器演示提前确认老师机器上的 MySQL 版本因为 5.x 用 com.mysql.jdbc.Driver8.x 用 com.mysql.cj.jdbc.Driver类名写错直接 ClassNotFoundException。如果不确定用 5.1.49 驱动连 MySQL 5.7 是兼容性最稳的组合课上演示翻车概率最低。下载驱动 jar 后在 IDE 里添加到项目的 Build Path。如果是命令行编译把 jar 放到项目 lib 目录然后 javac -cp lib/*.jar 编译。这一步繁琐但能逼你理解 classpath 概念答辩时老师问你的 mysql jar 放在哪里、干嘛用的就不怵。3.2 准备初始数据没有数据的系统没法演示建库脚本之后要准备一批初始数据不然打开系统是空荡荡的演示效果很差。我建议至少插一个管理员、一个收银员、两个商品INSERT INTO t_user (username, password, role) VALUES (admin, 123456, manager), (cashier1, 123456, cashier); INSERT INTO t_product (barcode, name, spec, unit, price, stock, min_stock) VALUES (690000000001, 农夫山泉 550ml, 550ml*1, 瓶, 2.00, 100, 20), (690000000002, 可乐 500ml, 500ml*1, 瓶, 3.50, 50, 20);密码字段这里先明文存后面避坑章节会讲加密的改进思路。商品条码用纯数字字符串国际条码一般是 13 位这里先用示例值后续在录入界面里再扩展校验逻辑。3.3 DBHelper把 JDBC 连接收敛到一个类里JDBC 的样板代码太多了如果每个 DAO 都写一遍 DriverManager.getConnection代码会膨胀到没法看。所以第一步是写一个 DBHelper 类把连接的创建和关闭收敛在一起import java.sql.*; public class DBHelper { private static final String URL jdbc:mysql://localhost:3306/supermarket_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai; private static final String USER root; private static final String PASSWORD 123456; static { try { // 注册 JDBC 驱动MySQL 8.x 必须写 com.mysql.cj.jdbc.Driver Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(Connection conn, Statement st, ResultSet rs) { if (rs ! null) { try { rs.close(); } catch (SQLException ignored) {} } if (st ! null) { try { st.close(); } catch (SQLException ignored) {} } if (conn ! null) { try { conn.close(); } catch (SQLException ignored) {} } } }这段代码里有几个参数不要抄完就完事。useUnicodetruecharacterEncodingutf8 保证中文不会乱码useSSLfalse 是因为本地开发不需要 SSL 握手少一个告警serverTimezoneAsia/Shanghai 解决 MySQL 8.0 的时区报错不写这个经常看到 The server time zone value...很多同学一头扎进中文乱码坑里其实根源是时区。close 方法里吞掉关闭异常是故意的关闭失败不能影响主流程但控制台会打出错误信息方便排查。还有一点这段代码里驱动类是 com.mysql.cj.jdbc.Driver对应 MySQL 8.0 的驱动 jar。如果 jar 是 5.x改成 com.mysql.jdbc.Driver同时 URL 里可以去掉 serverTimezone 参数其他不用动。3.4 登录功能界面到 DAO 的一路数据流登录是整个系统的入口也是面向对象编程 java思想最典型的体现一个 LoginDAO 负责数据库查询一个 User 类承载用户信息一个 LoginFrame 负责界面。先看 DAOpublic class LoginDAO { public User login(String username, String password) { // 用 ? 占位符避免字符串拼接导致的 SQL 注入 String sql SELECT id, username, role FROM t_user WHERE username ? AND password ?; try (Connection conn DBHelper.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, password); try (ResultSet rs ps.executeQuery()) { if (rs.next()) { User u new User(); u.setId(rs.getInt(id)); u.setUsername(rs.getString(username)); u.setRole(rs.getString(role)); return u; } } } catch (SQLException e) { e.printStackTrace(); } return null; } }这里用 PreparedStatement 而不是 Statement 字符串拼接是为了防 SQL 注入。一个很常见的反例是把 SQL 写成 SELECT * FROM t_user WHERE username username AND password password 功能上没问题但答辩时老师输入一个 or 11 就能直接登录。用 ? 占位符 setString 传参参数会被数据库引擎当作纯数据处理注入字符没有执行机会这是 JDBC 里必须讲清楚的知识点。登录界面部分按钮事件调 DAO 的写法JButton loginBtn new JButton(登录); loginBtn.addActionListener(e - { String username usernameField.getText().trim(); String password new String(passwordField.getPassword()); User user new LoginDAO().login(username, password); if (user null) { JOptionPane.showMessageDialog(this, 用户名或密码错误); } else { new MainFrame(user).setVisible(true); dispose(); } });这里用 getPassword() 而不是 getText() 取密码框内容是 Swing 的安全建议——密码框组件设计上就不应该让密码以 String 形式长期驻留内存。登录这种毫秒级查询在事件线程里跑没关系但后面销售结算涉及多表写入就必须丢后台线程这个在避坑章节再讲。4. 核心业务做成能讲清楚的模块入库、销售、库存扣减都靠事务超市管理系统最有含金量的不是增删改查界面而是入库和销售这两个写操作涉及多张表的一致性。答辩老师真正想听的其实是这里。4.1 商品入库先写流水再更新库存两步必须同生共死商品入库在业务上要做两件事往 t_stock_in 插入一条入库记录同时把 t_product 里的 stock 加回去。任何一步失败另一步都得撤销。把这两步包在同一个事务里的代码长这样public void stockIn(StockInRecord record) throws SQLException { Connection conn DBHelper.getConnection(); try { // 关闭自动提交两条 SQL 构成一个完整事务 conn.setAutoCommit(false); String insertIn INSERT INTO t_stock_in (product_id, quantity, in_price, operator_id, create_time) VALUES (?, ?, ?, ?, NOW()); try (PreparedStatement ps conn.prepareStatement(insertIn)) { ps.setInt(1, record.getProductId()); ps.setInt(2, record.getQuantity()); ps.setBigDecimal(3, record.getInPrice()); ps.setInt(4, record.getOperatorId()); ps.executeUpdate(); } String updateStock UPDATE t_product SET stock stock ? WHERE id ?; try (PreparedStatement ps conn.prepareStatement(updateStock)) { ps.setInt(1, record.getQuantity()); ps.setInt(2, record.getProductId()); ps.executeUpdate(); } conn.commit(); } catch (SQLException e) { conn.rollback(); throw e; } finally { conn.setAutoCommit(true); conn.close(); } }setAutoCommit(false) 是关键。JDBC 默认每执行一条 SQL 就自动提交两条 SQL 之间一旦第二条失败第一条已经落库就会出现流水有了但库存没加的脏数据。关掉自动提交后只有执行到 commit() 时数据才真正生效任一步抛异常rollback() 会把所有已执行的操作全部推翻。finally 里把 setAutoCommit(true) 改回来也很重要因为连接要还给连接池复用不重置的话下个事务会带着旧状态。4.2 销售结算一张订单牵三张表用事务保住一致性销售是库存业务的另一面。一次结算要做三件事先往 t_sale 插入一个主单再往 t_sale_item 逐条插明细最后扣减 t_product 的库存。最容易出问题的顺序是扣库存——如果先扣库存后面明细插入失败库存就凭空少了如果先插明细再扣库存扣库存失败销售明细就多出来了。正确做法是把三步全部放进一个事务并把扣减库存写成带条件的 UPDATE让数据库帮我们挡住超卖public void checkout(Cart cart, int cashierId) throws SQLException { Connection conn DBHelper.getConnection(); try { conn.setAutoCommit(false); // 1. 创建销售主单取得自增主键作为 saleId String insertSale INSERT INTO t_sale (total_amount, cashier_id, create_time) VALUES (?, ?, NOW()); int saleId; try (PreparedStatement ps conn.prepareStatement(insertSale, Statement.RETURN_GENERATED_KEYS)) { ps.setBigDecimal(1, cart.getTotalAmount()); ps.setInt(2, cashierId); ps.executeUpdate(); try (ResultSet keys ps.getGeneratedKeys()) { keys.next(); saleId keys.getInt(1); } } // 2. 逐条写明细 扣减库存库存不足时整单回滚 String insertItem INSERT INTO t_sale_item (sale_id, product_id, price, quantity, subtotal) VALUES (?, ?, ?, ?, ?); String updateStock UPDATE t_product SET stock stock - ? WHERE id ? AND stock ?; for (CartItem item : cart.getItems()) { try (PreparedStatement ps conn.prepareStatement(insertItem)) { ps.setInt(1, saleId); ps.setInt(2, item.getProductId()); ps.setBigDecimal(3, item.getPrice()); ps.setInt(4, item.getQuantity()); ps.setBigDecimal(5, item.getSubtotal()); ps.executeUpdate(); } try (PreparedStatement ps conn.prepareStatement(updateStock)) { ps.setInt(1, item.getQuantity()); ps.setInt(2, item.getProductId()); ps.setInt(3, item.getQuantity()); int rows ps.executeUpdate(); if (rows 0) { // 匹配不到满足条件的行说明库存不足 throw new SQLException(库存不足: item.getProductId()); } } } conn.commit(); } catch (SQLException e) { conn.rollback(); throw e; } finally { conn.setAutoCommit(true); conn.close(); } }这段代码里需要掰开讲的参数有两个。第一prepareStatement 的第二个参数 Statement.RETURN_GENERATED_KEYS意思是让 JDBC 在执行 INSERT 后返回自增主键如果忘了这段saleId 就只能用 max(id) 之类的手段去查并发时会拿到错值。第二UPDATE 语句里的 stock ? 是防超卖的兜底当库存不足时MySQL 匹配不到满足 WHERE 条件的行执行影响的 rows 数为 0代码里据此抛异常触发整体回滚。这个写法比先 SELECT 查库存再 UPDATE更安全因为两条语句之间有间隔并发时另一个会话可能已经扣完了库存只有把条件写进 UPDATE 才能保证扣减是原子操作。Java 八股文里常考的数据一致性这一行就是最实在的落地答案。4.3 模糊查询与库存预警两条 SQL 撑起系统的智能感课设答辩中被问最多的另一个问题是你的系统有哪些查询功能。与其硬凑统计图不如先把两个高频查询做扎实商品模糊搜索和库存预警列表。public ListProduct searchProducts(String keyword) { String sql SELECT * FROM t_product WHERE name LIKE ? OR barcode LIKE ?; String like % keyword %; // 注意通配符拼在参数里不是拼在 SQL 里 } public ListProduct findLowStock() { String sql SELECT * FROM t_product WHERE stock min_stock ORDER BY stock ASC; }模糊查询的 LIKE 通配符要拼在参数里而不是拼在 SQL 里否则又回到 SQL 注入的老问题。另外要注意索引失效的边界如果商品表数据量小课设往往就几十行%keyword% 导致的全表扫描完全无所谓但你要知道前导通配符会让 barcode 上的唯一索引失效这属于 Java 基础面试题里偏底层的那类问题答得出来很加分。库存预警那条 SQL 用的是 t_product 上的冗余 stock 字段每笔入库、销售后这个字段被实时更新所以这里不需要复杂计算一条 ORDER BY 就能把最急缺的商品排在最前面。很多同学在这个功能上绕远路去写定时任务或者触发器其实对课设来说完全没必要。5. 踩坑血泪超市管理系统的 5 个常见问题排查课设项目做出来是一回事让它在不同机器上稳定跑起来是另一回事。这一章写的是我在类似项目里反复踩过的坑每条都按现象 → 原因 → 解决说清楚。5.1 中文乱码数据库、连接、界面三层必须统一现象界面上商品名显示成?????或乱码符号MySQL 命令行里查出来也是乱码。原因三层各说各话——建库时用了 latin1JDBC 连接串没带 characterEncodingSwing 界面用了不支持中文的字体。任何一层不一致都会乱。解决建库脚本统一写成 utf8mb4连接串把 useUnicodetruecharacterEncodingutf8 带上Swing 界面给组件设置支持中文的字体。三个地方都改齐乱码基本消失。注意 MySQL 8.0 默认字符集已经是 utf8mb4但如果是接手老项目要用 SHOW CREATE TABLE t_product 确认表级字符集不要只看数据库级。5.2 ClassNotFoundExceptioncom.mysql.cj.jdbc.Driver现象程序一运行就报 ClassNotFoundException或者No suitable driver found。原因驱动 jar 没有加入 classpath或 jar 是 5.x 但代码里写的是 8.x 驱动类名或 jar 在项目里但没被 IDE 部署到运行环境。解决先在 IDE 里确认 jar 已被 Build Path 引用。如果都用命令行 javac/java编译和运行命令都要加 -cp 参数例如 java -cp .;lib/mysql-connector-java-8.0.33.jar com.supermarket.LoginFrame。Windows 上分号分隔Linux 和 macOS 用冒号这个细节也常踩。5.3 日期被多打印出.0现象销售单上的 create_time 显示为 2025-06-11 14:30:22.0小票上多了一个 .0。原因ResultSet.getTimestamp() 返回的 java.sql.Timestamp 继承自 java.util.DatetoString() 默认输出毫秒部分。直接放到 JLabel 就会带 .0。解决统一用 SimpleDateFormat 格式化后再显示new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(timestamp)。如果用了 Java 8 的 LocalDateTimeJDBC 驱动 8.x 支持 rs.getObject(create_time, LocalDateTime.class)代码更干净也不用再担心 .0 的问题。5.4 库存变成负数现象库存可以卖到 -5欠货了还能继续结账。原因扣库存的 UPDATE 没有 WHERE stock ? 条件或扣库存和销售明细不在同一个事务里或根本没有扣库存逻辑只改了界面数字。解决按 4.2 的写法强制 UPDATE ... WHERE id ? AND stock ?并检查返回行数。如果行数不够还要继续说明事务边界漏了。这个坑是课设里最减分的点老师只要看到库存负数前面做得再好都会被质疑务必在答辩前把库存不足的测试场景走一遍。5.5 点击按钮后窗口卡死现象销售结算时点击确定整个窗口冻结过几秒才恢复入库大批量数据时界面完全不动。原因Swing 是单线程模型所有事件都在事件分发线程EDT上执行。JDBC 查询和事务提交是阻塞操作放在按钮的 ActionListener 里会直接卡死 UI。解决把耗时操作丢进后台线程查询完成后用 SwingUtilities.invokeLater 把结果推回 EDT。最简单的写法new Thread(() - { try { checkoutService.checkout(cart, cashierId); SwingUtilities.invokeLater(() - JOptionPane.showMessageDialog(frame, 结算成功)); } catch (SQLException ex) { SwingUtilities.invokeLater(() - JOptionPane.showMessageDialog(frame, 结算失败: ex.getMessage())); } }).start();待办事项在后台线程执行弹窗通过 invokeLater 回到事件线程界面就不会冻结。课设数据量小可能不卡得明显但如果做批量导入或查询报表这个坑一定会炸。6. 答辩前必做的 5 个验证场景把会跑变成会讲课设做到能跑只是及格。答辩是现场表演必须在演示前把最容易让系统出丑的场景全过一遍。下面是我默认每个项目都会走的验证清单验证场景操作步骤预期结果库存不足拦截把某商品库存改成 1在收银台一次买 3 件弹库存不足销售单和库存都不变事务回滚结算时临时在代码里抛一个异常整单回滚库存与订单流水均无新增特殊字符商品名称带中文引号和特殊符号正常显示不乱码快速连点结算按钮连点两下只生成一张销售单不重复扣库存数据库重启结算完成后重启 MySQL 再查询流水数据持久化不丢失每一行都能演示成加分项。其中事务回滚是最值得准备的在结算代码里临时写一个 throw new RuntimeException然后展示库存和订单同时回滚。这一招比任何 PPT 都能说明你真的理解了 JDBC 事务。另外准备一个边界说明。老师问你的系统还有哪些不足时不要慌诚实说出三个改进方向一是密码没有做 MD5 加密目前是明文存储二是没有做商品销量排行和日结报表只留了查询接口三是权限只做了界面控制没有在数据库层做行级权限。这些话提前想好比临场支支吾吾强因为老师要的本来就不是完美系统而是你知道边界在哪里。我在每次提交课设前都会做一件事把数据库删掉重新跑一遍建库脚本和初始数据脚本然后从登录开始走完整条流程。这个习惯救过我很多次因为演示现场最怕的恰恰是自己机器上好好的换台电脑全崩。把换环境重跑当成验收标准系统才算真的稳了。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑