news 2026/10/5 7:25:51

Java+MyBatis+Swing班费管理系统:从部署到答辩全攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java+MyBatis+Swing班费管理系统:从部署到答辩全攻略

简介:这是一份基于Java、MyBatis与Swing技术栈开发的班费管理系统完整源码包,定位为数据库课程大作业,适合高校计算机相关专业学生在课程设计、毕业设计或项目起步阶段参考使用。项目代码经测试运行,评审得分94.5分,功能完整度较高。压缩包共88个文件,约156KB,包含36个Java源文件(业务逻辑与界面控制)、20个XML文件(MyBatis映射及Maven配置)、14个JFD窗体设计文件、12张系统运行截图以及2份SQL数据库脚本,结构清晰,便于直接导入IDE查看和二次开发。目前已有424人学习浏览。通过本资源可快速了解Swing桌面端与MyBatis持久层集成的完整思路,掌握班级收支管理、数据表设计及可视化界面搭建方法,尤其适合作为同类管理系统的开发蓝本,在此基础上按需扩展功能。

1. 班费管理系统:为什么这个组合值得当作数据库大作业的样板

班费管理系统,这个选题在大学数据库课设、Java 实训里几乎年年出现。它本质上是一个桌面端的 CRUD 应用:管学生名单、管每笔班费收支、留一份操作记录,再加上几个统计视图。但多数人拿到的源码包,界面要么是硬编码表格、要么数据层和界面层挤在一个类里,答辩时老师问一句“这条数据怎么查出来的”就露馅。而这个标题里的组合——Java + MyBatis + Swing + SQL 数据库,恰好把“界面、数据访问、数据库结构”三层拆开:Swing 画窗口和表格,MyBatis 管 SQL 映射,SQL 脚本管表关系和初始化数据。适合谁?适合想把大作业交成“能跑、能讲、能改造”的人,也适合第一次接触 MyBatis 的 Java 初学者。如果你刚好要做课设,与其东拼西凑,不如把这个方案吃透,改个皮就当自己的作品。

2. 为什么是 Swing + MyBatis:桌面端大作业的选型逻辑与运行原理

2.1 这套组合适合什么规模:桌面 GUI + 轻量 ORM 的边界

先回答一个很多人答辩时答不上来的问题:都 2025 年了,为什么还在用 Swing,不选 JavaFX,或者干脆做 Web?

常见做法是:学校课程进度通常只教到 Swing,JavaFX 需要额外配置、maven 依赖更多,而 Web 项目要装 Tomcat、写前端页面,课设周期根本来不及。Swing 的优势是 JDK 自带、双击就能跑、代码量少,一个 JFrame 就能把增删改查的界面搭出来。更关键的是,Swing 的 JTable 天然适合把数据库的二维表结构直接呈现出来,这和班费管理系统“看列表、记账、统计”的需求完全对得上。而 MyBatis 选它而不是 JDBC、也不是 Hibernate,原因就三条:SQL 是手写的,出错时你能在数据库工具里原样复现;结果映射很灵活,查出来的列可以直接塞进 Map 或自定义实体类;XML 配置把 SQL 集中在 mapper 文件里,答辩时摊开给老师看比散落在 Java 代码里清晰得多。

这套组合的边界也很清楚:它适合并发量极低、单机使用、数据量几千条以内的小型管理系统。如果以后要上多用户、浏览器访问、远程部署,这套界面层就得整个换掉。但作为课设,选型完全立得住,关键是你得把“为什么这样选”说给老师听,而不是只说“我会用”。

2.2 MyBatis 的 XML 配置流程:从 XmlConfigBuilder 到会话工厂

很多新手拿着班费管理系统的源码,第一次看到 mybatis-config.xml 时是一头雾水的。黑匣子感来自哪里?来自你对 MyBatis 启动过程只有模糊印象。我一般会把这条链路讲清楚,哪怕你不改它,也得知道它怎么干活。

MyBatis 的启动入口是SqlSessionFactoryBuilder,它拿到 mybatis-config.xml 的输入流后,会交给XMLConfigBuilder逐节点解析。解析顺序是有讲究的:先读<properties>,把 db.properties 里的键值对加载进来;再读<settings>,处理驼峰映射、日志实现这类全局开关;接着是<typeAliases>和<typeHandlers>,注册别名和类型处理器;然后解析<environments>,确定事务管理器类型和数据源参数;最后解析<mappers>,把每个 mapper XML 文件的位置注册进去。全部解析完成后,XMLConfigBuilder生成一个Configuration对象,SqlSessionFactoryBuilder用它构建出DefaultSqlSessionFactory。

重点来了:这个Configuration对象是 MyBatis 的“总账本”,所有 mapper 里的每一条 SQL 都会被解析成MappedStatement,连同参数映射、结果映射一起存进去。当你的 Java 代码调用sqlSession.getMapper(FeeMapper.class)时,MyBatis 用 JDK 动态代理生成一个实现类,你调接口方法,它就去Configuration里找对应的MappedStatement,执行 SQL,再用结果映射封装返回。这就是“为什么我写个接口不用写实现类就能查数据”的答案。理解了这条链,你去看源码包里那个XmlConfigBuilder相关的报错、去调typeHandler处理日期字段,心里就有谱了。

再补一个常见的误解:<mappers>里配置的 URL,加载的是 mapper XML,而不是接口类。接口类是要通过mapper标签的class属性,或者扫描包名的方式注册的。课设代码里最常见的是<mapper resource="mapper/FeeMapper.xml"/>这种写法,它要求 XML 的 namespace 必须等于接口的全限定名,否则启动直接报BindingException。

2.3 班费系统的 4 张核心表:表结构先定,能省一半返工

拿到任何“源码 + SQL 数据库”的课设包,第一步不要急着跑,先看 SQL 脚本。班费管理系统通常由这几张表构成:

表名用途关键字段
student班级成员名单id, stu_no, stu_name, class_name
fee_type班费类型字典id, type_name(如“班费收入”“活动支出”)
fee_record收支明细流水id, stu_id, fee_type_id, amount, fee_date, remark
user系统登录账号id, username, password, real_name

fee_record是核心,它用外键stu_id关联student,用fee_type_id或直接冗余一个fee_type字符串来区分收入支出。课设级别不追求第三范式,常见做法是保留fee_type冗余字段,查询时少一次 JOIN,写起来也简单。金额字段必须写DECIMAL(10,2),而不是 FLOAT——这一点我在第 4 章会专门讲,因为这是翻车重灾区。

看表结构时顺手检查三样东西:有没有主键、有没有外键、插入数据的时间字段格式是什么。很多 SQL 脚本里fee_date是DATETIME类型,包含时分秒;而 Swing 的JTable显示日期时如果你用了java.util.Date直接格式化,就很容易踩 12 小时制的坑。把表结构钉死,再去写 mapper 和界面,比代码写一半再回头改表要省一半时间。

3. 从解压到跑通:班费管理系统的部署步骤与最小配置

3.1 解压后先看这几个文件:目录里每一样是干嘛的

拿到压缩包,先别急着双击。我会先按这个顺序浏览目录,三十秒内判断这个包是否完整、能不能跑。

一眼看过去应该有四类东西:src目录存放 Java 源码,内部按controller、service、dao、entity、view分包,这是标准的 MVC 化 Dart 结构(Swing 场景下 view 层放 JFrame);resources目录放 mybatis-config.xml、db.properties 和 mapper XML;lib目录放着 MySQL 驱动、MyBatis、lombok 之类的依赖 jar 包;根目录里则是class_fee.sql或类似名字的数据库脚本,以及几张jpg/png格式的系统示例图片。

系统示例图片对你第一个作用是“验收标准”:启动后界面应该长成什么样,哪些按钮在什么位置,照着重现一次,比对着代码猜效率高。第二个作用是答辩 PPT 素材,别删,留着放“系统展示”页。

如果发现lib里缺 MySQL 驱动,先别慌——记住驱动版本和 MySQL 版本要对应。这个包大概率是 MySQL 5.7 时代写的,驱动类名可能是com.mysql.jdbc.Driver;你本地如果装的是 MySQL 8.x,就得换com.mysql.cj.jdbc.Driver,这两个类名差一个cj,报错时的提示完全不同,第 4 章会细讲。

3.2 导入数据库:MySQL 命令行与可视化工具两条路

先建库再导数据。打开你的 MySQL 客户端,执行:

CREATE DATABASE IF NOT EXISTS class_fee DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE class_fee; SOURCE /your/path/class_fee.sql;

这段 SQL 做了三件事:建库并指定utf8mb4字符集,避免中文乱码;切换到该库;执行脚本建表、灌数据。如果你用的是 Navicat、DataGrip、DBeaver 这类可视化工具,更快的方式是建好库后右键“运行 SQL 文件”选中脚本。无论哪条路,导入完成后务必做一次验证:

SHOW TABLES; SELECT COUNT(*) FROM student; SELECT * FROM fee_record LIMIT 5;

分别确认表的数量和关键表的初始化数据。这一步能提前暴露脚本里ENGINE=InnoDB被忽略、表没建全、或者 insert 语句里中文被写成乱码的问题。我踩过一回无声的坑:脚本执行”成功“,但fee_record表结构里把amount定义成了VARCHAR(20),插入的数字全变成字符串,MyBatis 映射成BigDecimal时直接类型转换异常。所以导入后要养成看DESC fee_record的习惯。

3.3 连接配置与启动:db.properties、mybatis-config.xml 和必经的环境变量坎

数据库导入成功,接下来的操作顺序是:先配连接、再改配置、最后启动。

打开resources/db.properties:

jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/class_fee?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai jdbc.username=root jdbc.password=你的密码

参数说明:useUnicode=true&characterEncoding=utf8保证中文字符正常读写;serverTimezone=Asia/Shanghai是 MySQL 8.x 连接时的时区必备参数,不加它驱动会报The server time zone value的错。jdbc.password一定改成你自己本机的 MySQL 密码,包里的默认密码要么是root要么是123456,不改的话跑到一半被拒绝连接,是最常见的启动失败原因。

确认mybatis-config.xml里的数据源引用了这些属性:

<dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource>

这里用了${}占位符,表示从 db.properties 里取值。POOLED是连接池类型,课设量级完全够用;如果你看到报错说“无法解析 db.properties”,检查一下<properties resource="db.properties"/>里的文件名和 resources 目录下是否一致,大小写敏感。

启动前最后检查 Java 环境变量——这也是热搜词里反复出现的“java环境变量配置详细教程”所涉及的坎。在命令行执行java -version和javac -version,两条命令都必须有输出,且版本一致。如果java能跑但javac报“不是内部命令”,说明只配了 JRE 路径没配 JDK,需要补JAVA_HOME指向 JDK 安装目录,并把它加到PATH里。我一般建议直接在 IntelliJ IDEA 里打开项目,让 IDE 自动识别 SDK,这样能绕开一半环境变量问题。最后找到包含public static void main的启动类,通常是LoginFrame或MainApp,运行后弹出登录窗口;用 SQL 脚本末尾 insert 进去的管理员账号登录,比如admin / admin123(不同包不同密码,以脚本注释为准)。这一步不需要你改任何业务代码,只要把环境理顺就能看到系统主界面。

4. 常见问题排查:班费管理系统翻车的 4 个高发点

4.1 现象:一点登录就报“Cannot create PoolableConnectionFactory”,控制台红字一片

原因:这条报错的根源几乎 100% 是数据库根本没连上。拆开看有四种具体可能:MySQL 服务没启动;端口不是默认的 3306;用户名密码与db.properties不一致;驱动版本和 MySQL 版本不匹配导致握手失败。

解决:按顺序排查,不要跳步。第一步,命令行执行net start mysql(Windows)或systemctl status mysql(Linux/Mac)确认服务在跑。第二步,用 Navicat 或 DBeaver 手动用同一组用户名密码连一次,能连上说明问题不在账号密码。第三步,看驱动类名:MySQL 8.x 必须用com.mysql.cj.jdbc.Driver,5.x 用com.mysql.jdbc.Driver,混用会出现Loading class is obsolete警告或Communications link failure。第四步,在jdbc.url末尾追加useSSL=false&allowPublicKeyRetrieval=true。MySQL 8 默认启用 caching_sha2_password 认证,老驱动不升级就报Public Key Retrieval is not allowed,这个参数就是开后悔药。改完配置重启程序,不要去刷新 Maven——这个包大概率没有 maven,是原生 jar 导入,改驱动 jar 要手动替换lib里对应的文件。

4.2 现象:MyBatis 查询返回的stuName是 null,其他字段正常,但把同一句 SQL 复制到 Navicat 能查出数据

原因:这是 MyBatis 结果映射的经典坑。Java 实体类属性叫stuName(驼峰),数据库列叫stu_name(下划线)。如果mybatis-config.xml的<settings>里没有开启地图下划线转驼峰,MyBatis 就找不到属性与之对应,返回 null。

解决:两种修法,推荐双管齐下。在<settings>中显式开启:

<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>

同时在 mapper XML 里写别名兜底:

<select id="selectFeeList" resultType="map"> select f.id, s.stu_name as stuName, f.fee_type as feeType, f.amount, date_format(f.fee_date, '%Y-%m-%d') as feeDate from fee_record f left join student s on f.stu_id = s.id order by f.fee_date desc </select>

逻辑说明:resultType="map"表示把每行结果封装成一个 Map,键就是 SQL 里的列名或别名。as stuName直接让返回结果的键和前端 JTable 的表头对齐,省掉后续在 Java 代码里再转一次的麻烦。date_format把时间格式化成长日期字符串,避免 JTable 渲染里出现Thu Jan 01 00:00:00 CST 2025这种不友好的格式。

参数说明:mapUnderscoreToCamelCase只对实体类属性映射生效,对resultType="map"不生效——Map 的键仍然是数据库返回的原始列名,所以别名兜底不是多余的。这是很多老代码明明开了驼峰映射、查出来的 Map 却还是带下划线的根本原因。

4.3 现象:班费余额计算对不上,明明只记了一笔 0.1 的支出,余额却显示 0.30000000000000004

原因:源码里如果用double或float存金额,就逃不过 IEEE 754 浮点精度问题。0.1 在二进制里是无限循环小数,累加几次误差就显形了。班费系统天天算钱,这个错看起来很“玄学”,其实是因为底层数据类型就没选对。

解决:数据库字段改为DECIMAL(10,2),实体类属性改为java.math.BigDecimal,传入金额时用字符串构造器:

BigDecimal amount = new BigDecimal(textField.getText().trim());

参数说明:new BigDecimal("0.1")是准确的,new BigDecimal(0.1)反而会得到一个近似值,所以千万别图省事用new BigDecimal(double)重载。界面上展示时用amount.setScale(2, RoundingMode.HALF_UP)取两位小数。这个坑是答辩加分点——老师问“你如何处理金额精度”,你能脱口说出“用 BigDecimal 而不是浮点型”,印象分直接拉满。

4.4 现象:界面中文全部变成乱码,示例图片路径也显示不出来

原因:乱码分两层。第一层是数据库向 MyBatis 传数据时的编码问题,连接串里没带characterEncoding=utf8,MySQL 返回的中文直接按默认编码转换坏了。第二层是 Swing 界面本身的渲染问题,Windows 上 Swing 默认字体对中文支持差,或者控制台输出乱码但界面正常。图片路径丢同理——源码里写的是"images/logo.png"这种相对路径,而你解压后的项目根目录不对,或者工程没把图片目录标记为资源目录。

解决:连接串加characterEncoding=utf8和useUnicode=true;建表 SQL 里列默认字符集也确认是utf8mb4。界面字体可以改成:

UIManager.put("Label.font", new Font("微软雅黑", Font.PLAIN, 14)); UIManager.put("Button.font", new Font("微软雅黑", Font.PLAIN, 14));

图片路径建议写成相对 classpath 的方式:

new ImageIcon(MainFrame.class.getResource("/images/logo.png"));

参数说明:getResource从 classpath 根目录找资源,只要/images目录被打进输出目录,不管项目换到哪台电脑都不会丢路径。不要再拼new File("images/logo.png"),这个写法在 IDE 里能跑,打包成 jar 必挂——因为文件在 jar 这个压缩包内部,操作系统路径里根本找不到它。“图片空白”最省事也是最稳妥的验证方式:在target/classes(或 out/production)目录里手动确认images文件夹是否存在及大小写是否一致。

4.5 现象:程序能启动,但 JFrame 窗口空白、转圈不动,鼠标移上去变转圈图标

原因:这个现象叫“卡死但没有异常堆栈”。本质上你把耗时操作或Thread.sleep()放到了 Swing 的事件分发线程(EDT)上。Swing 是单线程模型,所有界面刷新都必须在 EDT 里执行;如果你的主线程里先连数据库查了一大堆数据再开窗口,EDT 被业务代码占住,界面就没机会重绘。

解决:把耗时查询挪出 EDT,窗口创建用SwingUtilities.invokeLater:

public static void main(String[] args) { SwingUtilities.invokeLater(() -> { LoginFrame frame = new LoginFrame(); frame.setVisible(true); }); }

而登录按钮里的数据库查询逻辑,适合放在Thread里执行,拿到结果后再把数据交给 EDT 刷新 JTable:

new Thread(() -> { List<FeeRecord> list = feeMapper.selectAll(); SwingUtilities.invokeLater(() -> { DefaultTableModel model = new DefaultTableModel(data, columns); table.setModel(model); }); }).start();

逻辑说明:数据库查询走子线程,查完通过invokeLater把“更新表格”这个任务排到 EDT 队尾,界面就不会卡。这是 Swing 性能里最重要的一条规则,也是老师问“你的界面为什么丝滑”时你可以回答的技术点。一个小小的基本常识是:这里不适合改成“同步调用 + 进度条”,课设没这个必要,保持简单反而更容易讲清楚——你就说“查询在后台线程做,防止分析报表时长查询把界面锁死”,这句答辩话术就够了。

5. 答辩加分的三个改造方向:从“能跑”到“说得清”

5.1 用 BigDecimal 和 GROUP BY 做收支统计,替换主界面的“拍脑袋”汇总

原始系统的统计多半是遍历列表后循环累加余额。改造方向是在 mapper 里直接聚合:

select case when f.amount >= 0 then '收入' else '支出' end as bizType, count(*) as cnt, sum(abs(f.amount)) as total from fee_record f group by bizType;

返回后在 Swing 的统计面板里渲染成两张卡片:一张显示总收入、总支出、当前余额,另一张用 JProgressBar 按比例展示收支持比。这个改造代码量小,但效果直观,答辩时能讲“SQL 聚合代替内存计算”,属于一眼就能听出的专业表达。

5.2 给收支明细加日期范围查询和导出 CSV

这是老师最爱问的“扩展性”问题。在查询界面加两个日期选择框(JDateChooser 或直接文本框yyyy-MM-dd格式),mapper 里加动态 SQL:

<select id="selectByDateRange" resultType="map"> select * from fee_record <where> <if test="startDate != null and startDate != ''"> and fee_date &gt;= #{startDate} </if> <if test="endDate != null and endDate != ''"> and fee_date &lt;= #{endDate} </if> </where> order by fee_date desc </select>

这里特别提醒:XML 里>和<要写成&gt;和&lt;,否则 XML 解析直接报错。再加一个“导出 CSV”按钮,用PrintWriter把 JTable 的数据写进本地文件,Excel 打开不乱码的写法是文件头加一行\uFEFF(BOM),这段代码十分钟能写完,但答辩演示时点一下导出再打开文件,效果比任何口头说明都有说服力。

5.3 把数据字典和 ER 图放进 PPT,能治“侃侃而谈却无依据”的硬伤

第三次答辩时老师问得最多的是“你这几张表的关系是什么”。你不能只口头说“一对多”,而是要把 ER 图和数据字典放上去:所有表的主键、外键、字段类型、注释,列成表格;student 和 fee_record 之间的一对多关系、fee_type 和 fee_record 之间的字典关系,用箭头标清楚。还有一点容易忽略的就是 MyBatis 缓存——如果老师问“你用了 MyBatis 为什么还要写缓存开关”,你能回答“一级缓存默认开启、作用范围是 SqlSession,二级缓存要手动开启且存在脏读风险,课设里没用到所以关闭”,这个回答能直接证明你不是只会抄代码。

我从第一次跑通别人的课设到今天,最深的感受是:课设作品本身是 60 分,剩下 40 分全在“出了问题时能不能自己排查、被问到选型时能不能说出理由”。源码包里的代码只能给你一个起点,真正值得投入时间的,是把第 4 章这几个高发点的原理搞明白——因为我遇到的所有答辩翻车,几乎都发生在数据库连接、浮点精度、结果映射这三件小事上。希望这个方案能把你的大作业从“能跑”变成“说得清”,也希望你在改造成自己想要的样子时,遇到 SQL 报错时先看一眼字符集和金额字段,遇到界面卡死时先想起 EDT,这会让你少走很多弯路。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 7:25:51

Redis 2.6到7.0版本演进全解析:核心特性、升级路径与避坑指南

这几年Redis版本的迭代节奏明显加快了&#xff0c;但大部分人对它的认知其实还停留在某一个时间切片上。我经常看到两种人&#xff1a;一种是新项目刚起步&#xff0c;稀里糊涂选了3.x的老版本&#xff0c;只因为"网上教程都是这么写的"&#xff1b;另一种是生产环境…

作者头像 李华
网站建设 2026/10/5 7:25:38

OpenIPC刷机实战:君正T31旧摄像头改造为开源可控的RTSP监控设备

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 7:24:41

Winform Ribbon 控件源码:把Office式工具栏搬进老项目

简介&#xff1a;面向C# WinForm开发者提供一套完整的Ribbon控件源码&#xff0c;用于在桌面应用中实现Office风格选项卡式工具栏&#xff0c;覆盖按钮、菜单、下拉列表、文本框等常见命令元素&#xff0c;弥补原生控件缺少现代Ribbon界面的不足。包体共212个文件、487KB&#…

作者头像 李华
网站建设 2026/10/5 7:23:59

AI智能体安全实战:从Openclaw部署到Owlfy本地守护

最近折腾 openclaw 的时候&#xff0c;我在 PowerShell 里撞上了一堵墙&#xff1a;部署脚本跑了一半直接报错&#xff0c;提示 openclaw 无法安全验证 WSL2 环境&#xff0c;请运行 wsl --status 自查。我第一反应以为是环境变量没配好&#xff0c;结果检查一圈才发现&#xf…

作者头像 李华
网站建设 2026/10/5 7:23:23

ABB机器人ModbusTCP通信实战:RAPID实现Float字节序转换与PLC数据交互

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 7:22:58

YOLOv8防护服穿戴检测:从目标检测原理到项目部署全流程

简介&#xff1a;一份基于YOLOv8的实验室防护服穿戴规范检测项目&#xff0c;面向计算机、自动化等专业的毕业设计、课程设计及入门进阶人群&#xff0c;专注解决安全着装自动识别与可视化评估问题。压缩包仅8个文件&#xff0c;包含3个Python脚本、3个PyTorch权重文件与2个说明…

作者头像 李华