Java Swing + MySQL 宿舍管理系统课程设计:从登录到退宿完整实现与避坑指南

发布时间:2026/10/9 8:19:53
Java Swing + MySQL 宿舍管理系统课程设计:从登录到退宿完整实现与避坑指南 简介这是一套面向高校计算机相关专业学生的MySQL课程设计完整方案以Java Swing构建桌面端学生宿舍管理系统配套数据库脚本与全部源代码适合正在准备课程设计、毕业设计或需要Java桌面开发练手项目的学习者参考。压缩包共334个文件约108.12MB其中47个java源文件承载核心业务逻辑202个class为编译产物另有22张png界面截图、9个xml配置及db数据库文件、jar依赖包等工程结构完整可直接导入IDE运行调试。内容涵盖管理员管理、宿舍管理、学生管理、学生宿舍分配及多角色登录等模块界面组件与业务接口分层清晰便于理解Swing事件驱动与JDBC数据访问的配合方式。目前已有192人学习下载适合作为课程设计模板或二次开发基础帮助读者快速掌握从建库建表到界面交互的完整实现思路。1. 从一份课程设计说起Java Swing MySQL 的宿舍管理系统到底能跑多远很多计算机专业的学生在做课程设计时都会遇到同一个场景题目发下来是「学生宿舍管理系统」要求用 Java 写界面、用 MySQL 存数据最后交一份源代码和数据库脚本。听起来不难但真正动手时才发现Swing 的布局能把人逼疯JDBC 连接总是报错MySQL 安装配置教程翻了三遍还是连不上。这个标题指向的正是这样一套完整方案用 Java Swing 做桌面端界面用 MySQL 做数据持久化实现宿舍、学生、入住、退宿等核心管理功能。它适合正在做课程设计的学生也适合想用一个小项目练手 Java 桌面开发和数据库操作的初学者。源代码和数据库脚本是这套方案的核心交付物理解它们如何组织、如何跑通比单纯复制粘贴更有价值。2. 技术选型与整体架构为什么是 Swing JDBC 而不是别的2.1 Swing 在课程设计里的真实定位Java Swing 是 JDK 自带的一套 GUI 工具包不需要额外引入任何依赖这对于课程设计来说是一个巨大的优势。你不需要配置 Maven 仓库、不需要处理版本冲突只要装了 JDK 就能开始写界面。很多同学会问为什么不选 JavaFX答案很直接JavaFX 从 JDK 11 开始就不再随 JDK 一起发布了需要单独引入模块对于只想快速交作业的场景来说多一步配置就多一个翻车点。Swing 的核心组件包括 JFrame窗口、JPanel面板、JButton按钮、JTable表格、JTextField文本输入框等。一个典型的宿舍管理系统界面通常由登录窗口、主窗口、以及各个功能面板组成。主窗口一般用 JFrame 加上菜单栏 JMenuBar功能面板用 JPanel 配合 CardLayout 或者 JTabbedPane 来切换。JTable 用来展示学生列表、宿舍列表、入住记录等数据配合 DefaultTableModel 可以很方便地从数据库查询结果填充数据。Swing 的布局管理器是新手最容易踩坑的地方。FlowLayout 会按照添加顺序排列组件BorderLayout 把面板分成东南西北中五个区域GridLayout 把面板切成等大的网格GridBagLayout 最灵活但也最复杂。我一般会推荐用 BorderLayout 做整体框架中间放 JTable顶部放查询条件面板底部放操作按钮。这样结构清晰调整起来也方便。提示Swing 不是线程安全的所有界面更新操作必须放在事件调度线程EDT中执行。如果你在后台线程里直接修改 JTable 的数据模型可能会出现界面卡死或者数据错乱。2.2 MySQL 数据库表结构设计宿舍管理系统的数据库一般需要以下几张核心表学生表student、宿舍表dormitory、入住记录表check_in、管理员表admin。学生表存学号、姓名、性别、班级、联系方式等宿舍表存宿舍编号、楼栋、楼层、床位数、已住人数等入住记录表关联学生和宿舍记录入住时间和退宿时间。建表时需要注意几个关键点。第一主键用自增整数还是业务编号我建议学生表用学号作为主键宿舍表用宿舍编号作为主键这样查询时更直观。第二外键约束要不要加课程设计里加上外键可以体现数据库设计的完整性但插入数据时顺序不对会报错需要先插主表再插从表。第三字符集统一用 utf8mb4避免中文乱码。CREATE DATABASE dorm_management DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE dorm_management; CREATE TABLE student ( student_id VARCHAR(20) PRIMARY KEY COMMENT 学号, name VARCHAR(50) NOT NULL COMMENT 姓名, gender ENUM(男,女) DEFAULT 男 COMMENT 性别, class_name VARCHAR(50) COMMENT 班级, phone VARCHAR(20) COMMENT 联系电话 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学生信息表; CREATE TABLE dormitory ( dorm_id VARCHAR(20) PRIMARY KEY COMMENT 宿舍编号, building VARCHAR(20) NOT NULL COMMENT 楼栋, floor INT COMMENT 楼层, capacity INT DEFAULT 4 COMMENT 床位数, occupied INT DEFAULT 0 COMMENT 已住人数 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT宿舍信息表; CREATE TABLE check_in ( id INT AUTO_INCREMENT PRIMARY KEY, student_id VARCHAR(20), dorm_id VARCHAR(20), check_in_date DATE, check_out_date DATE, FOREIGN KEY (student_id) REFERENCES student(student_id), FOREIGN KEY (dorm_id) REFERENCES dormitory(dorm_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT入住记录表;上面这段 SQL 可以直接在 MySQL 命令行或者 Navicat 里执行。注意 ENGINEInnoDB 是必须的因为只有 InnoDB 支持外键。utf8mb4 字符集能兼容 emoji 和生僻字虽然宿舍管理系统不一定用得上但养成习惯没坏处。check_in 表的 id 用自增整数做主键因为一个学生可能多次入住退宿用学号做主键会冲突。2.3 JDBC 连接层的封装思路Java 连接 MySQL 的标准方式是 JDBC。你需要把 mysql-connector-java 的 jar 包放到项目的 classpath 下然后通过 DriverManager.getConnection 获取连接。直接在每个 DAO 方法里写连接代码会导致大量重复我一般会封装一个 DBUtil 类提供获取连接和关闭资源的方法。import java.sql.*; public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/dorm_management?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 123456; 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) { e.printStackTrace(); } try { if (stmt ! null) stmt.close(); } catch (SQLException e) { e.printStackTrace(); } try { if (conn ! null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }这段代码里几个参数需要根据你的环境调整。URL 中的 localhost 换成你的 MySQL 主机地址3306 是默认端口dorm_management 是数据库名。useSSLfalse 在本地开发时建议加上否则 MySQL 8.0 会报 SSL 警告。serverTimezoneAsia/Shanghai 是必须的不然时间字段会差 8 小时。characterEncodingutf8 保证中文不乱码。USER 和 PASSWORD 换成你自己的 MySQL 账号密码。注意MySQL 8.0 的驱动类名是 com.mysql.cj.jdbc.DriverMySQL 5.x 是 com.mysql.jdbc.Driver。用错驱动类会报 ClassNotFoundException这是新手最常见的翻车点之一。3. 核心功能模块的代码实现从登录到退宿的完整链路3.1 登录模块与权限校验登录窗口是整个系统的入口。一个典型的登录界面包含用户名输入框、密码输入框、登录按钮和取消按钮。点击登录后从 admin 表里查询匹配的记录如果存在则打开主窗口否则弹出提示。import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.sql.*; public class LoginFrame extends JFrame { private JTextField usernameField; private JPasswordField passwordField; public LoginFrame() { setTitle(宿舍管理系统 - 登录); setSize(350, 220); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); JPanel panel new JPanel(new GridLayout(3, 2, 10, 10)); panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); panel.add(new JLabel(用户名)); usernameField new JTextField(); panel.add(usernameField); panel.add(new JLabel(密码)); passwordField new JPasswordField(); panel.add(passwordField); JButton loginBtn new JButton(登录); JButton cancelBtn new JButton(取消); panel.add(loginBtn); panel.add(cancelBtn); loginBtn.addActionListener(new ActionListener() { Override public void actionPerformed(ActionEvent e) { String username usernameField.getText().trim(); String password new String(passwordField.getPassword()).trim(); if (checkLogin(username, password)) { dispose(); new MainFrame().setVisible(true); } else { JOptionPane.showMessageDialog(null, 用户名或密码错误); } } }); cancelBtn.addActionListener(e - System.exit(0)); add(panel); } private boolean checkLogin(String username, String password) { String sql SELECT * FROM admin WHERE username ? AND password ?; try (Connection conn DBUtil.getConnection(); PreparedStatement pstmt conn.prepareStatement(sql)) { pstmt.setString(1, username); pstmt.setString(2, password); ResultSet rs pstmt.executeQuery(); return rs.next(); } catch (SQLException e) { e.printStackTrace(); return false; } } }这段代码用 PreparedStatement 而不是 Statement目的是防止 SQL 注入。setString 方法会自动处理引号和特殊字符。checkLogin 返回 true 后关闭登录窗口并打开主窗口这是标准的流程。密码字段用 JPasswordField 而不是 JTextField输入内容会显示为圆点这是基本的安全习惯。3.2 学生信息管理增删改查的 Swing 实现学生信息管理面板通常包含一个 JTable 展示所有学生顶部有搜索框底部有添加、修改、删除按钮。JTable 的数据来自 DefaultTableModel每次操作后刷新模型即可。import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.sql.*; import java.util.Vector; public class StudentPanel extends JPanel { private JTable table; private DefaultTableModel model; public StudentPanel() { setLayout(new BorderLayout()); String[] columns {学号, 姓名, 性别, 班级, 电话}; model new DefaultTableModel(columns, 0) { Override public boolean isCellEditable(int row, int column) { return false; } }; table new JTable(model); add(new JScrollPane(table), BorderLayout.CENTER); JPanel btnPanel new JPanel(); JButton addBtn new JButton(添加); JButton editBtn new JButton(修改); JButton deleteBtn new JButton(删除); JButton refreshBtn new JButton(刷新); btnPanel.add(addBtn); btnPanel.add(editBtn); btnPanel.add(deleteBtn); btnPanel.add(refreshBtn); add(btnPanel, BorderLayout.SOUTH); refreshBtn.addActionListener(e - loadData()); deleteBtn.addActionListener(e - deleteSelected()); addBtn.addActionListener(e - showAddDialog()); loadData(); } private void loadData() { model.setRowCount(0); String sql SELECT * FROM student; try (Connection conn DBUtil.getConnection(); Statement stmt conn.createStatement(); ResultSet rs stmt.executeQuery(sql)) { while (rs.next()) { VectorString row new Vector(); row.add(rs.getString(student_id)); row.add(rs.getString(name)); row.add(rs.getString(gender)); row.add(rs.getString(class_name)); row.add(rs.getString(phone)); model.addRow(row); } } catch (SQLException e) { e.printStackTrace(); } } private void deleteSelected() { int row table.getSelectedRow(); if (row -1) { JOptionPane.showMessageDialog(this, 请先选中一行); return; } String studentId (String) model.getValueAt(row, 0); String sql DELETE FROM student WHERE student_id ?; try (Connection conn DBUtil.getConnection(); PreparedStatement pstmt conn.prepareStatement(sql)) { pstmt.setString(1, studentId); pstmt.executeUpdate(); loadData(); } catch (SQLException e) { JOptionPane.showMessageDialog(this, 删除失败可能存在关联的入住记录); } } private void showAddDialog() { JTextField idField new JTextField(); JTextField nameField new JTextField(); JComboBoxString genderBox new JComboBox(new String[]{男, 女}); JTextField classField new JTextField(); JTextField phoneField new JTextField(); Object[] message { 学号, idField, 姓名, nameField, 性别, genderBox, 班级, classField, 电话, phoneField }; int option JOptionPane.showConfirmDialog(this, message, 添加学生, JOptionPane.OK_CANCEL_OPTION); if (option JOptionPane.OK_OPTION) { String sql INSERT INTO student (student_id, name, gender, class_name, phone) VALUES (?, ?, ?, ?, ?); try (Connection conn DBUtil.getConnection(); PreparedStatement pstmt conn.prepareStatement(sql)) { pstmt.setString(1, idField.getText().trim()); pstmt.setString(2, nameField.getText().trim()); pstmt.setString(3, (String) genderBox.getSelectedItem()); pstmt.setString(4, classField.getText().trim()); pstmt.setString(5, phoneField.getText().trim()); pstmt.executeUpdate(); loadData(); } catch (SQLException e) { JOptionPane.showMessageDialog(this, 添加失败 e.getMessage()); } } } }loadData 方法每次清空表格模型再重新查询虽然效率不高但对于课程设计的数据量来说完全够用。deleteSelected 里捕获了 SQLException 并提示可能存在关联记录这是因为外键约束会阻止删除有入住记录的学生。showAddDialog 用 JOptionPane 弹出一个简单的表单适合快速实现。3.3 宿舍分配与退宿逻辑宿舍分配的核心是更新 check_in 表和 dormitory 表的 occupied 字段。分配时先检查宿舍是否已满然后插入入住记录并增加已住人数。退宿时更新退宿日期并减少已住人数。public boolean assignDorm(String studentId, String dormId) { String checkSql SELECT capacity, occupied FROM dormitory WHERE dorm_id ?; String insertSql INSERT INTO check_in (student_id, dorm_id, check_in_date) VALUES (?, ?, CURDATE()); String updateSql UPDATE dormitory SET occupied occupied 1 WHERE dorm_id ?; try (Connection conn DBUtil.getConnection()) { conn.setAutoCommit(false); try (PreparedStatement checkStmt conn.prepareStatement(checkSql)) { checkStmt.setString(1, dormId); ResultSet rs checkStmt.executeQuery(); if (!rs.next()) return false; int capacity rs.getInt(capacity); int occupied rs.getInt(occupied); if (occupied capacity) return false; } try (PreparedStatement insertStmt conn.prepareStatement(insertSql); PreparedStatement updateStmt conn.prepareStatement(updateSql)) { insertStmt.setString(1, studentId); insertStmt.setString(2, dormId); insertStmt.executeUpdate(); updateStmt.setString(1, dormId); updateStmt.executeUpdate(); conn.commit(); return true; } catch (SQLException e) { conn.rollback(); throw e; } } catch (SQLException e) { e.printStackTrace(); return false; } }这里用了事务来保证一致性。先查宿舍容量再插入记录最后更新已住人数三步要么全成功要么全回滚。setAutoCommit(false) 开启事务commit 提交rollback 回滚。如果不加事务插入成功但更新失败会导致数据不一致。退宿逻辑类似把 insert 换成 update check_out_date把 occupied 1 换成 occupied - 1。4. 避坑与排查那些年我们踩过的 MySQL 和 Swing 的坑4.1 坑一MySQL 8.0 连接报 Public Key Retrieval is not allowed现象用 JDBC 连接 MySQL 8.0 时抛出异常「Public Key Retrieval is not allowed」。原因MySQL 8.0 默认使用 caching_sha2_password 认证插件JDBC 驱动在获取公钥时被拒绝。解决在连接 URL 后面加上 allowPublicKeyRetrievaltrue或者把用户的认证插件改成 mysql_native_password。我一般直接在 URL 里加参数改起来最快。4.2 坑二Swing 界面中文乱码现象JTable 或者 JLabel 里的中文显示成方框或者问号。原因项目源码文件的编码和 JVM 运行时的默认编码不一致。Windows 中文版的默认编码是 GBK而你的 Java 文件可能是 UTF-8。解决在启动参数里加上 -Dfile.encodingUTF-8或者在 IDE 里把项目编码统一设为 UTF-8。数据库连接 URL 里也要加 characterEncodingutf8。4.3 坑三外键约束导致删除失败现象删除学生时弹出「Cannot delete or update a parent row: a foreign key constraint fails」。原因check_in 表里有该学生的入住记录外键约束阻止删除。解决先删除关联的入住记录再删除学生。或者在建表时把外键的 ON DELETE 设为 CASCADE但课程设计里不建议这么做因为级联删除容易误删数据。4.4 坑四JTable 数据更新后界面不刷新现象数据库里已经插入了新记录但 JTable 里看不到。原因DefaultTableModel 没有重新加载数据或者你在非 EDT 线程里修改了模型。解决每次增删改后调用 loadData() 重新查询并填充模型。如果是在后台线程里操作用 SwingUtilities.invokeLater 包裹界面更新代码。4.5 坑五MySQL 服务启动失败现象命令行执行 net start mysql 提示「服务正在启动 . 服务无法启动」。原因data 目录初始化失败或者 my.ini 配置文件路径不对。解决检查 MySQL 安装目录下的 data 文件夹是否存在如果为空需要执行 mysqld --initialize-insecure 重新初始化。my.ini 里的 basedir 和 datadir 路径要用反斜杠或者双反斜杠。5. 进阶技巧让这套系统更像一个能拿得出手的作品5.1 用 DAO 模式解耦界面与数据访问前面的代码把 SQL 直接写在 Swing 面板里对于课程设计来说能跑通就行。但如果你想在答辩时显得更有设计感可以把数据访问逻辑抽到独立的 DAO 类里。比如 StudentDao 提供 findAll、insert、deleteById 等方法StudentPanel 只负责调用 DAO 并渲染界面。这样界面和数据层分离后续换数据库或者加缓存都不用改界面代码。public class StudentDao { public ListStudent findAll() throws SQLException { ListStudent list new ArrayList(); String sql SELECT * FROM student; try (Connection conn DBUtil.getConnection(); Statement stmt conn.createStatement(); ResultSet rs stmt.executeQuery(sql)) { while (rs.next()) { Student s new Student(); s.setStudentId(rs.getString(student_id)); s.setName(rs.getString(name)); s.setGender(rs.getString(gender)); s.setClassName(rs.getString(class_name)); s.setPhone(rs.getString(phone)); list.add(s); } } return list; } }Student 是一个普通的 JavaBean只有属性和 getter/setter。DAO 返回 List 界面层遍历列表填充 JTable。这种写法在答辩时能体现出你对分层架构的理解比把所有代码堆在一个类里强得多。5.2 用表格模型自定义渲染提升可读性JTable 默认的单元格渲染是左对齐文本你可以自定义 TableCellRenderer 来改变字体颜色、背景色或者对齐方式。比如已满的宿舍用红色背景显示未满的用绿色。这个技巧在答辩演示时很加分代码量也不大。table.getColumnModel().getColumn(4).setCellRenderer(new DefaultTableCellRenderer() { Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component c super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); int occupied Integer.parseInt(table.getValueAt(row, 4).toString()); int capacity Integer.parseInt(table.getValueAt(row, 3).toString()); if (occupied capacity) { c.setBackground(Color.RED); } else { c.setBackground(Color.WHITE); } return c; } });这段代码假设第 3 列是床位数第 4 列是已住人数。渲染器每次绘制单元格时都会调用根据数值动态设置背景色。注意 isSelected 为 true 时不要覆盖选中颜色否则用户选中行时会看不到高亮效果。5.3 数据库备份与一键初始化脚本课程设计交付时数据库脚本是必须的。我习惯把建库、建表、插入初始数据的 SQL 写在一个 init.sql 文件里答辩前直接执行一遍就能恢复环境。初始数据至少包含一个管理员账号和几条测试用的学生、宿舍记录。INSERT INTO admin (username, password) VALUES (admin, admin123); INSERT INTO student VALUES (2024001, 张三, 男, 计算机2401, 13800000001); INSERT INTO student VALUES (2024002, 李四, 女, 计算机2402, 13800000002); INSERT INTO dormitory VALUES (A101, A栋, 1, 4, 0); INSERT INTO dormitory VALUES (A102, A栋, 1, 4, 0);执行完这些 SQL 后系统里就有可用的测试数据了。答辩时如果老师让你现场演示你可以先跑一遍 init.sql 再启动程序整个过程不到一分钟。5.4 打包成可执行 JAR 的注意事项最后一步是把项目打包成可执行 JAR。在 IDE 里选择 Export - Runnable JAR file把 mysql-connector-java 的 jar 包一起打进去。启动命令是 java -jar dorm-management.jar。如果报「no main manifest attribute」说明 MANIFEST.MF 里没有指定 Main-Class需要手动加上。我一般会在项目根目录放一个 run.bat内容就是 java -jar dorm-management.jar双击就能运行。这样交付给老师的时候不需要他配置任何环境只要装了 JDK 和 MySQL 就能跑起来。这套方案我从头到尾跑过不止一遍每次都会在数据库连接和界面刷新上花不少时间调试。后来我把 DBUtil 和 init.sql 固定下来新项目直接复制这两个文件省下来的时间可以用来打磨界面细节。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询