
简介本资源是一套面向高校计算机相关专业学生的MySQL课程设计完整方案采用Java Swing桌面端与MySQL数据库组合实现学生宿舍管理系统适合正在准备课程设计、毕业设计或需要Java桌面开发练手项目的学习者。压缩包共334个文件约108.12MB其中47个java源文件与202个class编译文件构成核心业务代码另有22个png界面素材、9个xml配置、若干C工程文件及db数据库文件、jar依赖包等覆盖从源码到可运行程序的完整链路。内容围绕宿舍管理场景展开包含管理员管理、宿舍管理、学生管理、学生宿舍分配等模块组件可帮助读者理解Swing界面布局、事件处理与JDBC数据库访问的配合方式。目前已有192人学习下载适合作为课程设计参考模板便于快速搭建项目框架、对照实现增删改查功能并梳理系统模块划分思路。1. 从一份“能跑起来”的宿舍管理系统说起mysqlJavaswing 到底能做出什么很多同学做课程设计时第一反应是去搜“学生宿舍管理系统源代码”下载下来发现要么跑不起来要么数据库对不上要么界面丑得没法演示。其实用 mysql Java swing 这套组合做宿舍管理是课程设计里最稳的一条路MySQL 负责数据持久化Java 负责业务逻辑Swing 负责桌面端交互三者都是 JDK 自带或极易安装的组件不需要额外配服务器、不需要前端框架一台笔记本就能完整跑通。这套方案能覆盖宿舍楼管理、房间分配、学生入住退宿、来访登记、水电费记录等典型模块适合计算机相关专业做课程设计、毕业设计雏形也适合刚学完 Java 基础想找一个完整项目练手的同学。下面我按实际做项目的顺序把数据库设计、Swing 界面搭建、JDBC 连接、功能实现和踩坑点一次讲清楚你照着做就能得到一个能演示、能答辩的系统。2. 数据库先立住mysql 建库建表与字段设计2.1 为什么先把数据库定死再写 Java我见过太多人先拖 Swing 控件拖到一半发现字段不够用回头改数据库结果实体类、DAO、界面全要动。正确顺序是先画 E-R 图再写建表 SQL最后才写 Java。宿舍管理系统的核心实体只有五个楼栋、房间、学生、入住记录、管理员。关系是一栋楼有多个房间一个房间有多个床位一个学生同一时间只能住一个床位入住记录表负责把学生和床位关联起来并记录入住、退宿时间。这样设计的好处是退宿后历史记录还在方便查“这个床位以前住过谁”。2.2 建库建表 SQL 与字段说明-- 创建数据库字符集用 utf8mb4避免中文乱码 CREATE DATABASE dorm_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE dorm_db; -- 楼栋表 CREATE TABLE building ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL COMMENT 楼栋名称如1号楼, floors INT NOT NULL DEFAULT 6 COMMENT 楼层数, remark VARCHAR(200) DEFAULT NULL ); -- 房间表 CREATE TABLE room ( id INT PRIMARY KEY AUTO_INCREMENT, building_id INT NOT NULL, room_no VARCHAR(10) NOT NULL COMMENT 房间号如101, capacity INT NOT NULL DEFAULT 4 COMMENT 可住人数, occupied INT NOT NULL DEFAULT 0 COMMENT 已住人数, FOREIGN KEY (building_id) REFERENCES building(id) ); -- 学生表 CREATE TABLE student ( id INT PRIMARY KEY AUTO_INCREMENT, sno VARCHAR(20) NOT NULL UNIQUE COMMENT 学号, name VARCHAR(30) NOT NULL, gender CHAR(1) DEFAULT 男, phone VARCHAR(20), college VARCHAR(50) ); -- 入住记录表 CREATE TABLE checkin ( id INT PRIMARY KEY AUTO_INCREMENT, student_id INT NOT NULL, room_id INT NOT NULL, bed_no INT NOT NULL COMMENT 床位号1-4, checkin_time DATETIME DEFAULT CURRENT_TIMESTAMP, checkout_time DATETIME DEFAULT NULL, status TINYINT DEFAULT 1 COMMENT 1在住 0已退宿, FOREIGN KEY (student_id) REFERENCES student(id), FOREIGN KEY (room_id) REFERENCES room(id) ); -- 管理员表 CREATE TABLE admin ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(30) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL COMMENT 存MD5值别存明文 );字段设计上有三个点要注意。第一room表里冗余了occupied字段这是故意的因为每次查房间列表都要统计已住人数用冗余字段比每次 count 快代价是入住退宿时要同步更新。第二checkin表的status用 1/0 而不是直接删记录退宿只改状态和checkout_time历史可追溯。第三password存 MD5虽然课程设计不要求高安全但明文存密码是答辩时最容易被问住的点。2.3 初始化数据与自增主键的坑INSERT INTO building (name, floors) VALUES (1号楼, 6), (2号楼, 6); INSERT INTO room (building_id, room_no, capacity) VALUES (1, 101, 4), (1, 102, 4), (1, 201, 4), (2, 101, 4); INSERT INTO admin (username, password) VALUES (admin, MD5(123456));这里有个新手常翻车的地方AUTO_INCREMENT主键在删除记录后不会自动回填。比如你插了 1、2、3 号房间删了 2 号再插新房间id 会是 4 而不是 2。课程设计演示时如果按 id 排序显示顺序会看起来“跳号”。解决办法是显示时按room_no排序不要依赖 id 顺序。另外外键约束在批量插入时要注意顺序必须先插building再插room否则外键报错。3. Java 端分层实体类、DAO 与 JDBC 连接3.1 项目包结构怎么分才不乱我一般按这个结构建包entity放实体类dao放数据库操作util放工具类ui放 Swing 界面service放业务逻辑课程设计可以省略直接 DAO 调。实体类字段和数据库列一一对应用驼峰命名比如roomNo对应room_no。这样后面写 DAO 时映射关系清晰不会出现“这个字段到底对应哪列”的玄学问题。3.2 JDBC 工具类与连接参数package util; import java.sql.*; public class DBUtil { // 数据库连接参数按自己环境改 private static final String URL jdbc:mysql://localhost:3306/dorm_db?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 你的密码; static { try { 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 stmt, ResultSet rs) { try { if (rs ! null) rs.close(); } catch (SQLException e) {} try { if (stmt ! null) stmt.close(); } catch (SQLException e) {} try { if (conn ! null) conn.close(); } catch (SQLException e) {} } }连接串里三个参数必须写对useSSLfalse避免 MySQL 8 的 SSL 警告serverTimezoneAsia/Shanghai解决时区报错characterEncodingutf8保证中文不乱码。驱动类名 MySQL 8 用com.mysql.cj.jdbc.DriverMySQL 5 用com.mysql.jdbc.Driver写错会报ClassNotFoundException。密码填你本地 root 的密码如果忘了就在命令行用mysql -u root -p试。3.3 一个完整的 DAO 方法查询所有房间package dao; import entity.Room; import util.DBUtil; import java.sql.*; import java.util.ArrayList; import java.util.List; public class RoomDAO { public ListRoom findAll() { ListRoom list new ArrayList(); String sql SELECT r.id, r.room_no, r.capacity, r.occupied, b.name AS building_name FROM room r JOIN building b ON r.building_id b.id ORDER BY b.name, r.room_no; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { while (rs.next()) { Room room new Room(); room.setId(rs.getInt(id)); room.setRoomNo(rs.getString(room_no)); room.setCapacity(rs.getInt(capacity)); room.setOccupied(rs.getInt(occupied)); room.setBuildingName(rs.getString(building_name)); list.add(room); } } catch (SQLException e) { e.printStackTrace(); } return list; } }这段代码用try-with-resources自动关连接比手动 close 更稳。SQL 里用 JOIN 把楼栋名一起查出来避免界面显示时再查一次数据库。PreparedStatement防 SQL 注入虽然课程设计里查询条件简单但养成习惯答辩时是加分项。注意rs.getInt(id)里的列名要和 SELECT 里的别名一致写错会抛SQLException。4. Swing 界面搭建从登录窗到主界面的可复现步骤4.1 登录界面与事件绑定package ui; import dao.AdminDAO; import javax.swing.*; import java.awt.*; public class LoginFrame extends JFrame { private JTextField userField new JTextField(15); private JPasswordField passField new JPasswordField(15); public LoginFrame() { setTitle(宿舍管理系统登录); setSize(350, 220); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); setLayout(new GridBagLayout()); GridBagConstraints gbc new GridBagConstraints(); gbc.insets new Insets(8, 8, 8, 8); gbc.gridx 0; gbc.gridy 0; add(new JLabel(用户名), gbc); gbc.gridx 1; add(userField, gbc); gbc.gridx 0; gbc.gridy 1; add(new JLabel(密码), gbc); gbc.gridx 1; add(passField, gbc); JButton loginBtn new JButton(登录); gbc.gridx 0; gbc.gridy 2; gbc.gridwidth 2; add(loginBtn, gbc); loginBtn.addActionListener(e - { String user userField.getText().trim(); String pass new String(passField.getPassword()); if (new AdminDAO().login(user, pass)) { dispose(); new MainFrame().setVisible(true); } else { JOptionPane.showMessageDialog(this, 用户名或密码错误); } }); } public static void main(String[] args) { SwingUtilities.invokeLater(() - new LoginFrame().setVisible(true)); } }界面用GridBagLayout而不是绝对定位这样窗口缩放时控件不会错位。登录按钮用 lambda 写监听器代码短且清晰。SwingUtilities.invokeLater是 Swing 的规矩所有界面创建都放在事件调度线程里否则可能出现界面闪烁或卡死。密码用JPasswordField取出来是 char 数组转 String 后传给 DAO 做 MD5 比对。4.2 主界面用 JTabbedPane 分模块主界面不要把所有功能堆在一个窗口里用JTabbedPane分成“房间管理”“学生管理”“入住退宿”“查询统计”四个标签页。每个标签页里放一个JPanel面板里用JTable显示数据上面放JToolBar放增删改按钮。JTable的数据用DefaultTableModel刷新时先setRowCount(0)清空再重新 add比重新 new 一个 JTable 省事。表格列名用中文比如“楼栋”“房间号”“容量”“已住”和数据库字段对应但显示更友好。4.3 入住与退宿的业务逻辑入住操作要在一个事务里做三件事往checkin插一条记录、把room.occupied加 1、检查是否超过capacity。退宿则反过来更新checkin的status和checkout_time、把room.occupied减 1。这三步必须用同一个 Connection 并手动提交否则中途失败会出现“记录插了但人数没加”的数据不一致。代码里用conn.setAutoCommit(false)成功后commit()异常时rollback()。这是课程设计里最能体现你懂事务的地方答辩时主动讲。5. 避坑与排查课程设计里最容易翻车的 5 个点5.1 中文乱码数据库、连接串、Swing 三处都要设现象界面上显示“1号楼”变成“1??”或者插入中文报错。原因通常是数据库字符集不是 utf8mb4或者 JDBC 连接串没加characterEncodingutf8。解决建库时指定DEFAULT CHARACTER SET utf8mb4连接串加characterEncodingutf8Swing 里如果读文件才需要设字体直接显示数据库内容一般不用。三处都设了还乱码检查 MySQL 配置文件my.ini里的character-set-server。5.2 驱动报错ClassNotFoundException 与时区异常现象启动时报com.mysql.cj.jdbc.Driver找不到或者The server time zone value ?D1ú±ê×?ê±?? is unrecognized。原因没把mysql-connector-java.jar加到项目 classpath或者连接串没写serverTimezone。解决在 IDEA 里 File → Project Structure → Libraries 添加 jar 包连接串加上serverTimezoneAsia/Shanghai。MySQL 8 的驱动包版本要和数据库版本匹配5.7 的库用 8.0 驱动一般也能连但反过来可能报错。5.3 外键约束导致插入失败现象插入房间时报Cannot add or update a child row: a foreign key constraint fails。原因room.building_id引用的楼栋 id 不存在。解决先插楼栋再插房间或者临时SET FOREIGN_KEY_CHECKS0关掉检查不推荐演示完记得开回来。更稳的做法是在 DAO 里先查楼栋是否存在不存在就提示用户先建楼栋。5.4 表格数据不刷新模型没通知视图现象点了“添加房间”按钮数据库里确实插入了但 JTable 还是旧数据。原因直接改了数据库但没刷新DefaultTableModel。解决每次增删改后调用tableModel.setRowCount(0)再重新addRow或者调用tableModel.fireTableDataChanged()。我一般封装一个refreshTable()方法所有操作后都调一次省得漏。5.5 连接泄漏忘了关 ResultSet 和 Statement现象程序跑一会儿就报Too many connections。原因每次查询都 new Connection 但没关连接池耗尽。解决用try-with-resources或者DBUtil.close()在 finally 里关。课程设计并发量小但养成关连接的习惯答辩时被问到“连接怎么管理”能答上来。如果用了连接池比如 Druid记得在配置文件里设maxActive。6. 进阶技巧把课程设计做成能写进简历的项目6.1 用 MD5 加盐存密码别再用明文登录那块admin表存的是MD5(123456)但 MD5 裸哈希容易被彩虹表撞。进阶做法是加盐注册时生成随机盐值存到salt字段密码存MD5(password salt)。登录时先按用户名查出盐再算哈希比对。代码只多几行但答辩时讲“我做了加盐哈希”比“我存了 MD5”高一个档次。盐值用UUID.randomUUID().toString().substring(0, 8)生成即可。6.2 用 JFreeChart 给宿舍入住率加个图表课程设计如果全是表格演示效果平淡。可以引入 JFreeChart一个 jar 包在“查询统计”标签页里画一个柱状图显示每栋楼的入住率。数据从room表按building_id分组统计SUM(occupied)/SUM(capacity)。代码大概三十行但演示时图表一出来老师印象分直接拉满。注意 JFreeChart 的 jar 包要一起放进项目否则换台电脑跑不起来。6.3 导出 Excel用 Apache POI 把入住记录导出来答辩时老师常问“数据能不能导出”。用 Apache POI 写一个导出按钮把checkin表的数据写成.xlsx。核心代码是XSSFWorkbook、Sheet、Row、Cell四层。注意 POI 的 jar 包有好几个poi、poi-ooxml、commons-io 等缺一个就报NoClassDefFoundError。导出路径用JFileChooser让用户选别写死。这个功能代码量不大但让系统看起来“完整”。6.4 验证方法用 JUnit 测 DAO 层别只靠手点界面验证。给RoomDAO写几个 JUnit 测试testFindAll断言返回列表不为空testInsert插入后查出来数量加一。测试类放在test目录用Before初始化连接。这样改代码后跑一遍测试比重新点一遍界面快得多。课程设计不要求测试覆盖率但有几个测试用例说明你有工程意识。6.5 我踩过的一个血泪教训最后说个我自己的翻车经历。第一次做这个系统时我把所有 SQL 拼在 Java 字符串里改一个字段名要全局搜索替换结果漏了一处运行时才报Unknown column。后来我把建表 SQL 单独存成schema.sqlDAO 里只用PreparedStatement加参数改字段时先改 SQL 文件再改实体类最后改 DAO顺序固定就不容易漏。还有一次演示前没测退宿功能现场点下去报外键错误原因是退宿时先删了checkin记录再更新room顺序反了。从那以后我养成了一个习惯任何涉及多表操作的功能先在命令行用 SQL 手动跑一遍事务确认逻辑对了再写进 Java。希望这些经验能帮你少走点弯路顺利把课程设计跑起来。本文还有配套的精品资源点击获取