Java Swing进销存管理系统源码解析:环境搭建与反编译还原实战
简介这是一套基于Java Swing的进销存管理系统源码包适合Java桌面应用初学者、课程设计或毕业设计参考。系统覆盖客户/商品/供应商管理、进货与销售业务、库存盘点、查询统计及操作权限等核心模块能帮助理解传统桌面管理系统的分层与DAO设计思路开发环境为MyEclipse数据库采用SQL Server 2000并附带数据库文件。包内总计325个文件约4.47MB以Java源文件与编译后的class文件为主同时包含界面相关的png/gif图片、项目依赖的jar库、数据库备份文件mdf/ldf/db以及doc/ppt设计文档均按功能模块组织便于对照源码与文档进行学习。该资源已有599人学习下载适合需要完整可运行项目作为实践蓝本的读者可据此快速搭建环境、阅读业务逻辑并在此基础上扩展或改造为自己的系统。1. Java Swing进销存管理系统源码先别被一堆 .class 劝退Java Swing进销存管理系统源码这套包在群里流转过好几手真正打开跑通的人却不多。原因很直接解压之后你看到的不是一摞 .java 源文件而是一堆 .class 字节码于是有人骂一句“发了个寂寞”就删了。实际上这套系统是可跑可改的课设级项目信息管理、业务管理、库存盘点、查询统计、系统管理五个功能模块齐全数据库用 SQL Server 2000配套数据库文件也在包里。对正在做课程设计、毕业设计参照或者想练 Swing JDBC 老链路的人来说它的价值比那些空壳 demo 高得多。这篇就把它从头拆一遍环境怎么搭、源码怎么还原、业务怎么改、坑在哪按我的习惯全部提前踩一遍再写给你。2. 环境与数据库SQL Server 2000 附加和 JDBC 连接串的适配2.1 为什么这套系统绕不开 SQL Server 2000这套系统的技术栈是典型的 2005 年前后课设搭配MyEclipse 写 Swing 界面JDBC 直连 SQL Server 2000界面类命名直接用业务词DAO 层和界面层分得还算清楚。放到今天SQL Server 2000 是个老古董但理解它当年的使用习惯反而能帮你把 JDBC 的原理摸得更透。先说一个很多人卡住的事实SQL Server 2000 官方支持的系统是 Windows 2000/XP/Server 2003Windows 10 和 Windows 11 上安装程序直接拒绝运行。但这不代表这套系统跑不了你有两条路一是装虚拟机在 XP 镜像里把 SQL Server 2000 装好宿主机用 IDE 远程连二是直接用高版本 SQL Server2008 R2 及以上把包里的 .MDF 数据库文件附加进去2000 的数据库文件向上兼容附加基本都能成功。我自己的习惯是第二种少折腾一个虚拟机。2.2 数据库文件附加MDF 方式还是 SQL 脚本方式包里的“数据库文件”一般会给两种形态.MDF.LDF 物理文件或者一个 .sql 脚本文件。MDF 方式适合图形化操作SQL 脚本方式适合批量执行和版本管理两个都能用。在 SQL Server 2008 R2 及以上版本附加 MDF 的路径是打开 Management Studio右键“数据库”节点选“附加”然后添加 .MDF 文件路径。这里有个细节SQL Server 2000 的 MDF 文件附加到高版本后数据库兼容级别还是 80建议手动改成当前实例的级别否则执行某些语句时会有兼容性提示。如果是 SQL 脚本SQL Server 2000 时代没有 Management Studio用的是查询分析器和命令行工具 isql脚本执行方式长这样# 用 isql 执行脚本isql 是 SQL Server 2000 自带的命令行工具 isql -S 127.0.0.1 -U sa -P 123456 -d master -i inventory.sql参数说明-S 后面跟服务器地址本机就是 127.0.0.1-U 是登录名默认超级管理员是 sa-P 是密码SQL Server 2000 装完后 sa 密码默认是空虚拟机里装的时候建议直接设一个-d 指定默认数据库写 master 就行-i 指定要执行的 SQL 脚本文件路径。注意脚本里如果包含建库语句执行时会直接创建数据库不需要事先手工建。2.3 JDBC 驱动2000 版和老版本驱动不是一回事这套系统里 JDBC 连接 SQL Server 2000 用的驱动类名和 URL 格式跟 2005 之后完全不同这是最容易翻车的地方。2000 用的驱动是微软早期的三个 jar 包msbase.jar、mssqlserver.jar、msutil.jar驱动类是com.microsoft.jdbc.sqlserver.SQLServerDriverURL 格式要在jdbc后面多写一个microsoft。连接工具类的标准写法是下面这样拿到源码后第一件事就是改这个类的参数// DBUtil.java —— SQL Server 2000 的 JDBC 连接工具类 package com.inventory.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBUtil { // 注意2000 的驱动类名带 microsoft 段不是高版本的 com.microsoft.sqlserver.jdbc.SQLServerDriver private static final String DRIVER com.microsoft.jdbc.sqlserver.SQLServerDriver; // URL 格式jdbc:microsoft:sqlserver://主机:端口;DatabaseName库名 private static final String URL jdbc:microsoft:sqlserver://localhost:1433;DatabaseNameinventory; private static final String USER sa; private static final String PASSWORD 123456; // 改成你自己实例的 sa 密码 static { try { // 加载驱动只执行一次 Class.forName(DRIVER); } catch (ClassNotFoundException e) { // 找不到驱动说明三个 jar 没放对位置或者版本不对 e.printStackTrace(); } } public static Connection getConnection() throws SQLException { // 所有 DAO 都通过这个方法拿连接 return DriverManager.getConnection(URL, USER, PASSWORD); } }这段代码里需要注意三个参数。第一个是驱动类名2000 版必须带microsoft段如果你手上只有 sqljdbc4.jarSQL Server 2005 的驱动驱动类名要换成com.microsoft.sqlserver.jdbc.SQLServerDriverURL 也要去掉microsoft段两者必须匹配混用就报ClassNotFoundException或者UnsupportedOperationException。第二个是端口SQL Server 2000 默认实例监听 1433如果你装的是命名实例端口会变成动态端口需要到“服务器网络实用工具”里手动固定。第三个是密码SQL Server 2000 安装时如果选的 Windows 身份验证模式JDBC 用 sa 是登不进去的必须确认安装时选了“混合模式”。2.4 MyEclipse 导入工程与首次启动开发环境是 MyEclipse但实际用 Eclipse 或者 IntelliJ IDEA 也能跑Swing 项目不挑 IDE。导入方式很简单File - Import - Existing Projects into Workspace选择解压后的目录。导入后你会看到 src 目录里可能什么都没显示因为交付物是 .class 文件而不是 .java 源文件这个问题的处理放到下一章讲这里先解决运行环境。JDK 版本建议用 1.6 或 1.7太新的 JDK 跑 Swing 老代码通常没问题但万一遇到某些字体渲染问题不好排查。把三个 JDBC 的 jar 包放进项目的 lib 目录并加入 Build Path然后找到入口类 SystemMain右键 Run As - Java Application。如果控制台没有报错并且弹出了一个带菜单栏的窗口说明环境已经通了。首次运行前记得把 DBUtil 里的数据库名和密码都改成你自己的否则启动不报错但一登录就抛 SQL 异常。提示SQL Server 2000 安装完后默认可能没有启用 TCP/IP 协议连接前用“服务器网络实用工具”勾选 TCP/IP然后重启 SQL Server 服务不然 JDBC 永远连不上。3. 源码真相反编译还原 DAO 层与界面类的调用关系3.1 为什么包里全是 .class先判断这个工程完整不完整项目正文里的文件列表已经说明了问题SystemMain、GoodsInfo、GuestInfo、SeverInfo、SaleGoods、InGoods、JSalesQuery、GoodsInfoDao、InsertGoodsInfo、SaleDao全是 .class 后缀。这套系统原始交付的时候只打了编译产物没有把 .java 一起放进包里这种情况在早期的课设资源里非常常见不算坏消息因为 .class 文件是可以反编译的而且类名保留得很完整还原成本远低于从零重写。拿到一堆 class 文件第一步不是急着反编译而是先做静态分析看这个工程的类职责分布。按照命名习惯我把它们分成三组SystemMain 是入口主窗体SaleGoods、InGoods、JSalesQuery、InsertGoodsInfo 这些带业务动作词的类是各个业务界面和操作窗口GoodsInfo、GuestInfo、SeverInfo 是以实体名词结尾的类大概率是实体或者信息维护界面GoodsInfoDao、SaleDao 结尾带 Dao是数据访问层。把这个对应关系理清楚你才知道反编译之后每个文件要归到哪个包。3.2 反编译批处理JD-GUI 和 fernflower 怎么选反编译工具有图形化的 JD-GUI也有命令行的 fernflower两个都是免费工具。JD-GUI 适合单文件快速查看但遇到批量反编译就点得手酸fernflower 适合一次处理多个 class输出质量在开源工具里属于第一梯队。我的习惯是命令行批处理然后把反编译结果统一导入 IDE。# 用 fernflower 批量反编译-dgs1 表示保留行号信息 java -jar fernflower.jar -dgs1 \ ./classes/SystemMain.class ./classes/SaleGoods.class ./classes/InGoods.class \ ./classes/GoodsInfo.class ./classes/GuestInfo.class ./classes/SeverInfo.class \ ./classes/JSalesQuery.class ./classes/GoodsInfoDao.class ./classes/InsertGoodsInfo.class \ ./classes/SaleDao.class \ ./decompiled_output/命令里的-dgs1是 fernflower 的参数含义是生成调试信息这样反编译出来的代码里会保留行号后续调试打断点方便。输入文件可以写多个 class也可以写一个包含 class 的目录fernflower 会递归处理。最后一个参数是输出目录工具会自动建。反编译完成后每个 class 对应一个同名的 .java 文件把这些文件复制到项目的 src 目录下按原来的包结构摆放。处理完之后有一个容易忽略的步骤检查反编译代码里的编码。原项目在 MyEclipse 里很可能用的是 GBK 编码反编译工具默认按 UTF-8 解码中文注释和字符串会变成乱码。打开源文件看一眼如果中文全成了\uXXXX转义序列或者方块字就把 IDE 的文件编码改成 GBK 重新打开然后在 IDE 里做一次编码转换再保存。3.3 反编译后的 DAO 层长什么样还原一个查询方法反编译出来的代码风格和可读性取决于编译时的符号表类名、方法名、字段名都保留着所以还原度通常在八成以上。以 GoodsInfoDao 为例反编译回来大概率是这种结构我补全了泛型和资源释放的常见写法// GoodsInfoDao.java —— 商品信息查询反编译后整理 package com.inventory.dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.inventory.entity.GoodsInfo; import com.inventory.util.DBUtil; public class GoodsInfoDao { // 按编号或名称模糊查询商品 public ListGoodsInfo queryGoods(String keyword) { ListGoodsInfo list new ArrayListGoodsInfo(); // 用 LIKE 拼接模糊查询参数用 ? 占位防止 SQL 注入 String sql select goods_no, goods_name, unit, price, stock from tb_goods where goods_no like ? or goods_name like ?; Connection conn null; PreparedStatement ps null; ResultSet rs null; try { conn DBUtil.getConnection(); ps conn.prepareStatement(sql); // 两个条件都用同一个关键字百分号放在参数里而不是 SQL 里 ps.setString(1, % keyword %); ps.setString(2, % keyword %); rs ps.executeQuery(); while (rs.next()) { GoodsInfo g new GoodsInfo(); // 下划线命名转驼峰属性逐列取值 g.setGoodsNo(rs.getString(goods_no)); g.setGoodsName(rs.getString(goods_name)); g.setUnit(rs.getString(unit)); g.setPrice(rs.getDouble(price)); g.setStock(rs.getInt(stock)); list.add(g); } } catch (SQLException e) { e.printStackTrace(); } finally { // JDBC 资源释放顺序ResultSet - PreparedStatement - Connection if (rs ! null) { try { rs.close(); } catch (SQLException e) { } } if (ps ! null) { try { ps.close(); } catch (SQLException e) { } } if (conn ! null) { try { conn.close(); } catch (SQLException e) { } } } return list; } }这段代码里有几个点值得注意。第一个是参数占位符传参位置%通配符放在setString的参数里而不是拼进 SQL 字符串这样能避免注入反编译出来的原始代码里可能直接拼了字符串建议统一改成这种写法。第二个是finally块里的资源关闭顺序必须先关 ResultSet再关 PreparedStatement最后关 Connection顺序反了在某些老驱动下会报“连接已关闭”的异常。第三个是GoodsInfo实体类里的字段类型price用 double 在课设里常见但如果金额精度要求高最好改成BigDecimal这是后续改造的一个可选优化点。3.4 把它们重新编译回去缺什么依赖怎么补反编译源码整理好之后下一步是编译验证。直接用 javac 做一次命令行编译比在 IDE 里点按钮更能暴露依赖问题# Windows 下用 javac 编译整个 src 目录注意编码指定 GBK javac -encoding GBK -cp lib\mssqlserver.jar;lib\msbase.jar;lib\msutil.jar -d ./bin src/com/inventory/**/*.java-encoding GBK指定源码编码如果你之前已经把源文件转成了 UTF-8这里就改成-encoding UTF-8保持一致即可。-cp后面跟 classpathWindows 下多个 jar 用分号分隔Linux 和 macOS 用冒号。-d ./bin指定编译输出目录。编译如果报“找不到符号”大多数情况是实体类或者工具类的包名没对上检查 import 语句如果报“程序包不存在”说明有 jar 包没加进 classpath。编译通过后把 bin 目录下的 class 文件重新打成 jar 或者直接跑 IDE这套系统就能用了。到这一步你已经把一个“交付物只有 class”的项目完整还原成了可维护的源码工程后面改业务逻辑、加功能都是在你自己能看懂的基础上做了。4. 业务闭环梳理进货、销售、盘点与查询统计的数据流4.1 五个功能模块对应哪些表和界面这套系统的功能划分清晰五个模块各自对应一组界面类和数据库表理顺模块与表的对应关系后续改代码才有方向感。按正文描述整理成下面这张表模块界面/操作类涉及数据表核心操作信息管理GoodsInfo、GuestInfo、SeverInfotb_goods、tb_client、tb_supplier客户/商品/供应商增删改查业务管理SaleGoods、InGoods、InsertGoodsInfotb_sale、tb_in销售单录入、进货单录入库存管理盘点窗口tb_goodsstock 字段库存盘点与调整查询统计JSalesQuery 及查询窗口tb_sale、tb_in、tb_goods销售/入库/商品多条件查询系统管理登录窗口sys_user操作员登录与权限控制表结构是典型的 SQL Server 2000 风格主键用 int identity 自增金额用 numeric(18,2)字符串用 varchar日期用 datetime。商品表 tb_goods 至少有 goods_no、goods_name、unit、price、stock 五个字段销售表 tb_sale 至少有 goods_no、quantity、price、sale_date 四个字段这个结构在课设里几乎是标配。理解了这个骨架再看界面类里的代码你会发现每个界面做的事情高度一致查列表、填表单、点保存、刷新表格。4.2 销售单录入与库存扣减事务没补会出大事业务管理模块最核心的链路是销售单插入一条销售记录同时减少商品表里的库存。这两步操作必须放在同一个事务里否则会出现“销售单有了、库存没减”或者“库存减了、销售单没了”的数据不一致。课设代码里最常见的偷懒方式是在界面上分别调用两个 DAO 方法中间没有事务控制一旦第二步抛异常第一步已经提交了。还原 SaleDao 的时候我建议直接把销售逻辑改写成带事务控制的版本代码骨架如下// SaleDao.java —— 销售入账 库存扣减放在同一事务里 public boolean saleGoods(String goodsNo, int quantity, double price) { Connection conn null; PreparedStatement ps null; try { conn DBUtil.getConnection(); // 关键关闭自动提交后续两条 SQL 要么都成功要么都回滚 conn.setAutoCommit(false); // 第一步插入销售明细 String sqlSale insert into tb_sale(goods_no, quantity, price, sale_date) values(?, ?, ?, getdate()); ps conn.prepareStatement(sqlSale); ps.setString(1, goodsNo); ps.setInt(2, quantity); ps.setDouble(3, price); ps.executeUpdate(); ps.close(); // 先关闭第一条语句再复用变量 // 第二步扣减库存stock 字段直接做算术运算 String sqlStock update tb_goods set stock stock - ? where goods_no ?; ps conn.prepareStatement(sqlStock); ps.setInt(1, quantity); ps.setString(2, goodsNo); int rows ps.executeUpdate(); if (rows 0) { // 商品编号不存在主动回滚 conn.rollback(); return false; } // 两步都成功统一提交 conn.commit(); return true; } catch (Exception e) { // 任何一个环节异常回滚全部操作 if (conn ! null) { try { conn.rollback(); } catch (SQLException e1) { } } e.printStackTrace(); return false; } finally { if (ps ! null) { try { ps.close(); } catch (SQLException e) { } } if (conn ! null) { try { conn.close(); } catch (SQLException e) { } } } }这段代码的核心是setAutoCommit(false)这一行。默认情况下 JDBC 是自动提交模式每条 SQL 执行完立刻生效所以把自动提交关掉两条 SQL 才变成一个原子操作。commit()在两条都成功时调用rollback()在异常时调用。这里有个细节第二步的executeUpdate()返回受影响的行数如果返回 0说明商品编号不存在此时要主动回滚不然第一条销售记录已经写进去了。参数传递上quantity 是 intprice 是 double分别用setInt和setDouble日期不走参数直接让数据库取当前时间getdate()。课设里还有一个常见问题卖货前没有校验库存是否充足。这个逻辑可以在事务开始前加一条查询也可以在 update 语句里加条件比如把 SQL 改成update tb_goods set stock stock - ? where goods_no ? and stock ?受影响行数为 0 就表示库存不足回滚并提示用户。这种改法比先查再更新更安全避免并发场景下两个请求同时超卖。4.3 查询统计JSalesQuery 里那几条常用 SQL查询统计模块的典型场景是按时间段查销售记录、按商品名模糊查、按客户查往来。JSalesQuery 这个类反编译出来后里面基本都是拼 SQL 的逻辑。因为查询条件是可选的老代码通常用字符串拼接的方式动态加 where 条件这种写法容易出两个问题一个是条件为空时 SQL 语法错误另一个是拼接时忘了加空格。建议改成固定模板加条件判断的方式。-- 销售查询按时间段 商品名模糊查关联商品表取名称 SELECT g.goods_name, s.quantity, s.price, s.sale_date FROM tb_sale s LEFT JOIN tb_goods g ON s.goods_no g.goods_no WHERE s.sale_date 2024-01-01 AND s.sale_date 2024-12-31 AND g.goods_name LIKE %键盘% ORDER BY s.sale_date DESC;这条 SQL 里LEFT JOIN和INNER JOIN的区别要注意销售单中的商品编号在商品表里一定存在用哪种 JOIN 结果都一样但如果未来要统计“哪些商品从未卖出”就得用LEFT JOIN加IS NULL条件来实现反连接。LIKE %键盘%这种写法在数据量小的时候没问题数据量大了走不了索引课设阶段不用纠结性能但心里要有数。4.4 库存盘点与系统管理的实现逻辑库存盘点模块在课设里通常做得比较简陋核心就是一个 update 语句把商品表的库存改成盘点后的实际数量。但严谨的做法是记录盈亏也就是“实盘数量 - 账面数量”正数是盘盈负数是盘亏。如果你要完善这个模块建议在商品表里加一个 check_quantity 字段记录实盘数再在盘点记录表里记录差异和盘点时间这样才能追溯。系统管理模块对应操作员表和登录窗口常见实现是登录时查 sys_user 表比对用户名和密码匹配成功后在内存里存一个登录标记。课设版的权限控制一般是硬编码的比如操作员和管理员用同一个界面但某些按钮置灰。这一块反编译还原后基本能用不用大改重点是确认登录查询用的是参数占位符而不是字符串拼接否则存在注入风险。5. 老项目踩坑记录五个让课设跑不起来的典型问题5.1 驱动类找不到ClassNotFoundException 从哪来现象运行程序控制台第一行就是java.lang.ClassNotFoundException: com.microsoft.jdbc.sqlserver.SQLServerDriver程序直接退出。原因lib 目录里放的不是 SQL Server 2000 的驱动常见情况有三种——jar 包根本没放进来、放的是 sqljdbc4.jar 这种高版本驱动、驱动类名写错。解决确认 lib 下有没有 msbase.jar、mssqlserver.jar、msutil.jar 三个文件把项目里所有com.microsoft.jdbc.sqlserver.SQLServerDriver的类名统一同时检查 Build Path 里有没有对应的 jar 条目。如果只有 sqljdbc4.jar就把驱动类名改成com.microsoft.sqlserver.jdbc.SQLServerDriverURL 去掉microsoft段两个版本绑定使用不能混。5.2 连接超时端口和协议都是隐形杀手现象登录时卡住几十秒最后报Communications link failure或者Connection refused: connect。原因SQL Server 2000 默认情况下监听的是 1433 端口但如果你装的是命名实例、没有启用 TCP/IP 协议、或者 Windows 防火墙拦了端口JDBC 就连不上。解决打开“服务器网络实用工具”确认 TCP/IP 协议已启用用netstat -an | findstr 1433检查端口是否在监听如果端口不是 1433在连接串里显式指定端口格式是jdbc:microsoft:sqlserver://localhost:端口号;DatabaseName库名。另外把 SQL Server 服务管理器里的服务状态确认一下很多“连不上”其实是服务根本没启动。5.3 反编译出来的源码全是乱码编码问题不在于工具而在于源头现象用 JD-GUI 或者 fernflower 打开 class 文件代码逻辑能看但所有中文字符串都变成\uXXXX转义序列注释直接是乱码。原因原项目在 MyEclipse 里用 GBK 编码编写编译成 class 时字符串常量以 UTF-8 存储反编译工具默认按平台编码输出中文就炸了。解决强制性习惯是拿到 class 先不要急着反编译先用javap -verbose看一眼常量池确认字符串编码反编译工具里把输出编码显式设为 GBK生成 .java 文件后用 IDE 的“File Encoding”批量转换成 UTF-8再全局搜一下\u开头的字符串确认没有遗漏。我从那次之后每次反编译前都把输出编码固定为 GBK再统一转 UTF-8再也没有被乱码坑过。5.4 数据库附加失败文件版本和只读权限双重坑现象附加 MDF 时提示“文件正在使用”或者“无法附加数据库”有的机器直接提示版本不兼容。原因文件从压缩包里解压后带了只读属性或者 MDF 所在路径包含中文和特殊字符或者 SQL Server 服务账号没有该目录的读权限。解决先右键 MDF 和 LDF 文件取消“只读”勾选把文件放到纯英文路径下例如D:\sqldata\如果是权限问题给 SQL Server 服务账号赋予该目录的完全控制权限高版本实例附加 2000 文件一般没问题万一报版本不支持就用 SQL 脚本方式重建库。这里多说一句MDF 附加成功后建议立即做一次“脱机再联机”确认文件没有只读残留否则后续写入操作会报只读错误。5.5 中文存入数据库变问号varchar 和 nvarchar 的天壤之别现象界面里中文录入正常但查询数据库表时看到的中文全是???。原因SQL Server 2000 对 varchar 类型使用数据库默认代码页存储中文JDBC 连接串没有指定字符编码插入时中文字符在传输过程中被截断或者转换错误。解决建表时对可能存中文的列改用nvarchar类型SQL Server 的 nvarchar 以 Unicode 存储中文兼容性最好如果表已经建好用ALTER TABLE tb_goods ALTER COLUMN goods_name NVARCHAR(100)改列类型。同时在 JDBC 连接串里追加;charsetGBK参数2000 驱动支持的写法双管齐下能解决九成以上的中文乱码问题。6. 升级实战把数据库从 SQL Server 2000 迁到 MySQL6.1 迁移思路与 SQL 语法差异对照如果你想把这套系统跑在 MySQL 上或者干脆换到 MySQL 8 环境练习迁移成本并没有想象中高因为 JDBC 代码的改动集中在 DBUtil 一个类SQL 语句的差异用一张表就能覆盖。下面是必须处理的语法差异对照SQL Server 2000MySQL说明getdate()NOW()取当前时间销售单和进货单都要改ISNULL(expr, 0)IFNULL(expr, 0)查询统计里处理空值的函数TOP nLIMIT n分页和取前几条的写法完全不同identity(1,1) 自增AUTO_INCREMENT建表语句里的自增定义nvarchar(n)VARCHAR(n) CHARACTER SET utf8mb4MySQL 的 varchar 直接支持 Unicode无需 n 前缀[dbo].[table]去掉前缀2000 里常见的 schema 前缀要清理存储过程返回值视情况改写课设项目一般没用存储过程可忽略6.2 DBUtil 改造与连接串参数迁移时 DBUtil 类的改动最集中驱动类名、URL、占位符用法都要跟着变。MySQL 8 的连接写法如下// DBUtil.java —— MySQL 8 版本 private static final String DRIVER com.mysql.cj.jdbc.Driver; private static final String URL jdbc:mysql://localhost:3306/inventory ?useUnicodetruecharacterEncodingutf8 useSSLfalseserverTimezoneAsia/Shanghai; private static final String USER root; private static final String PASSWORD 123456;连接串里三个参数是关键characterEncodingutf8保证中文正常存取useSSLfalse避免 MySQL 8 默认开启 SSL 引起的告警serverTimezoneAsia/Shanghai指定时区否则驱动会报时区错误。改完 DBUtil 后把建表脚本里的getdate()全部替换成NOW()identity改成AUTO_INCREMENT建库时指定utf8mb4字符集其他 DAO 代码基本不用动。迁移完成后重启程序登录、进货、销售、查询各走一遍重点看中文和日期两个类型是否正常。从那以后我拿到任何老项目第一件事永远是先看 lib 目录里的驱动 jar 和连接串写法再决定要不要动数据库这个顺序能省掉一半的排错时间。这套系统的骨架是完整的功能闭环也清晰不管是交课设还是拿来练手跑通一遍的收获比看十篇教程都实在。希望帮到你。本文还有配套的精品资源点击获取