news 2026/10/20 4:39:52

Java学生信息管理系统实验报告:Swing+JDBC+MySQL从零实现增删改查

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java学生信息管理系统实验报告:Swing+JDBC+MySQL从零实现增删改查

简介:这份Java课程设计实验报告面向高校计算机相关专业学生及Java初学者,用于完成学生信息管理系统的课程设计或实验任务。报告围绕Java基本语法、面向对象编程、Swing图形界面、I/O处理及数据库连接等核心知识点展开,完整覆盖登录模块、学生信息增删改查模块以及管理员权限管理模块,并区分超级管理员与普通用户的操作权限。资源包内含1个doc文档,大小约1.15MB,内容包含实验目的、预习内容、实验设备与环境、实验内容、任务设计及程序清单等完整章节,附有可参考的源代码结构,便于读者对照理解系统实现思路与调试运行流程。目前已有6453人学习下载,适合需要快速搭建课程设计框架、梳理实验报告结构或查漏补缺Java开发基础的学习者参考使用。

1. 一份实验报告背后的真实工程:从零搭一个能跑的学生信息管理系统

很多同学拿到「JAVA学生信息管理系统实验报告.doc」这个任务时,第一反应是去搜一份现成的 Word 文档,改改封面、换换名字就交上去。但真正做过课程设计答辩的人都知道,老师翻两页就会问:你的数据存在哪?增删改查怎么保证不串数据?界面和数据库是怎么连的?这时候一份只有截图和几段文字的报告根本撑不住。这个标题真正指向的,是一套用 Java 实现的、带图形界面、能对学号姓名成绩做增删改查、并且能写进实验报告里讲清楚设计思路的完整小系统。它适合正在做 Java 课程设计的学生,也适合想用一个真实小项目把 JDBC、Swing、集合框架串起来练手的初学者。下面我按自己带人做课设的流程,把从环境到代码到报告写法拆开讲。

2. 先定技术栈再动手:Swing + JDBC + MySQL 的最小组合

2.1 为什么课设场景下这套组合最稳

学生信息管理系统这类课设,核心诉求不是高并发、不是分布式,而是「能在自己电脑上跑起来、能演示、代码量可控、报告里讲得清」。基于这个前提,我一般会推荐 Swing + JDBC + MySQL 的组合。Swing 是 JDK 自带的图形库,不需要额外装前端框架,一个JFrame加几个JTextField、JTable就能把界面撑起来;JDBC 是 Java 访问数据库的标准接口,学一次以后做任何数据库项目都能复用;MySQL 免费、资料多、装完就能用。

有人会问为什么不选 JavaFX 或者 Spring Boot 加网页。JavaFX 从 JDK 11 开始要单独引依赖,课设环境里经常因为模块化配置翻车;Spring Boot 做出来的东西确实更现代,但对一个只要求增删改查的课设来说,光是配 Maven、写 Controller、调前端就够耗掉大半时间,报告里还得解释一堆和「学生信息管理」本身无关的东西。所以除非老师明确要求 Web 方向,否则 Swing 这套是性价比最高的。

2.2 环境准备的具体版本和验证命令

动手前先把环境确认一遍,避免写到一半发现 JDK 版本不对。我一般用 JDK 8 或 JDK 17 这两个长期支持版本,MySQL 用 5.7 或 8.0 都行,驱动包用mysql-connector-java。下面这几条命令用来确认环境是否就绪。

# 确认 JDK 版本,输出里要能看到 1.8 或 17 java -version # 确认 MySQL 服务在跑,能进命令行 mysql -u root -p # 编译一个测试类,确认 javac 可用 javac -version

三条都通过之后,在 MySQL 里建库建表。表结构不用复杂,一张学生表就够,字段包括学号、姓名、性别、年龄、成绩。学号设成主键,因为它是天然唯一的。

-- 建库,字符集用 utf8mb4 避免中文乱码 CREATE DATABASE student_db DEFAULT CHARACTER SET utf8mb4; USE student_db; -- 学生表,sno 做主键保证学号不重复 CREATE TABLE student ( sno VARCHAR(20) PRIMARY KEY, name VARCHAR(50) NOT NULL, sex VARCHAR(4), age INT, score DOUBLE );

建完表可以用DESC student;看一眼字段类型对不对。这里有个细节:score用DOUBLE而不是FLOAT,因为成绩做排序和求平均时DOUBLE精度更稳,虽然课设数据量小感觉不出来,但报告里写清楚选型理由会加分。

2.3 项目目录结构和驱动引入

目录结构建议按职责分三层:界面层、数据访问层、实体类。这样报告里画结构图的时候层次清楚,老师一看就知道你懂分层。

StudentMS/ ├── lib/ │ └── mysql-connector-java-8.0.28.jar ├── src/ │ ├── entity/Student.java │ ├── dao/StudentDao.java │ ├── ui/MainFrame.java │ └── util/DBUtil.java

驱动 jar 包放进lib目录后,编译和运行时都要通过-cp把它加进类路径,否则会报ClassNotFoundException。这是新手最容易卡住的地方,后面避坑章节会专门讲。

3. 把增删改查写扎实:实体类、DAO 与 Swing 界面

3.1 实体类和数据库连接工具

实体类就是把表的一行映射成一个 Java 对象,字段和表字段一一对应。这一步看着简单,但它是后面所有操作的基础。

package entity; // 学生实体,字段与 student 表一一对应 public class Student { private String sno; private String name; private String sex; private int age; private double score; public Student() {} public Student(String sno, String name, String sex, int age, double score) { this.sno = sno; this.name = name; this.sex = sex; this.age = age; this.score = score; } // getter 和 setter 省略,实际写的时候每个字段都要有 public String getSno() { return sno; } public void setSno(String sno) { this.sno = sno; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } }

连接工具类负责统一管理数据库连接,把 URL、用户名、密码集中在一处,改的时候只改一个地方。

package util; import java.sql.Connection; import java.sql.DriverManager; public class DBUtil { // 数据库地址,库名要和建库时一致 private static final String URL = "jdbc:mysql://localhost:3306/student_db?useSSL=false&serverTimezone=UTC&characterEncoding=utf8"; 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 Exception { return DriverManager.getConnection(URL, USER, PASSWORD); } }

URL 里三个参数值得说明:useSSL=false关掉 SSL 警告,本地开发不需要;serverTimezone=UTC解决时区报错,这是 MySQL 8.0 驱动最常见的坑;characterEncoding=utf8保证中文不乱码。密码那一行换成自己 MySQL 的密码。

3.2 DAO 层:增删改查四个方法

DAO 层把所有 SQL 操作包起来,界面层只调方法不碰 SQL,这样职责清晰,报告里也好讲。

package dao; import entity.Student; import util.DBUtil; import java.sql.*; import java.util.ArrayList; import java.util.List; public class StudentDao { // 新增学生 public boolean add(Student s) { String sql = "INSERT INTO student(sno,name,sex,age,score) VALUES(?,?,?,?,?)"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, s.getSno()); ps.setString(2, s.getName()); ps.setString(3, s.getSex()); ps.setInt(4, s.getAge()); ps.setDouble(5, s.getScore()); return ps.executeUpdate() > 0; } catch (Exception e) { e.printStackTrace(); return false; } } // 按学号删除 public boolean delete(String sno) { String sql = "DELETE FROM student WHERE sno=?"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, sno); return ps.executeUpdate() > 0; } catch (Exception e) { e.printStackTrace(); return false; } } // 修改学生信息 public boolean update(Student s) { String sql = "UPDATE student SET name=?,sex=?,age=?,score=? WHERE sno=?"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, s.getName()); ps.setString(2, s.getSex()); ps.setInt(3, s.getAge()); ps.setDouble(4, s.getScore()); ps.setString(5, s.getSno()); return ps.executeUpdate() > 0; } catch (Exception e) { e.printStackTrace(); return false; } } // 查询全部,返回列表 public List<Student> findAll() { List<Student> list = new ArrayList<>(); String sql = "SELECT * FROM student ORDER BY sno"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery()) { while (rs.next()) { Student s = new Student( rs.getString("sno"), rs.getString("name"), rs.getString("sex"), rs.getInt("age"), rs.getDouble("score") ); list.add(s); } } catch (Exception e) { e.printStackTrace(); } return list; } }

四个方法都用了PreparedStatement而不是Statement,原因是它用占位符?传参,能防止 SQL 注入,也能避免字符串拼接时引号出错。try-with-resources写法保证连接和语句自动关闭,不用手写finally。查询方法返回List<Student>,界面层拿到列表后直接刷到表格里。

3.3 Swing 界面:表格加按钮的最小可用形态

界面不用做得花哨,一个表格显示数据,几个输入框加按钮完成操作就够了。核心是把 DAO 的方法接到按钮的点击事件上。

package ui; import dao.StudentDao; import entity.Student; import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.util.List; public class MainFrame extends JFrame { private JTable table; private DefaultTableModel model; private StudentDao dao = new StudentDao(); public MainFrame() { setTitle("学生信息管理系统"); setSize(700, 450); setDefaultCloseOperation(EXIT_ON_CLOSE); setLocationRelativeTo(null); // 表头与数据库字段对应 String[] cols = {"学号", "姓名", "性别", "年龄", "成绩"}; model = new DefaultTableModel(cols, 0); table = new JTable(model); add(new JScrollPane(table), BorderLayout.CENTER); // 底部按钮区 JPanel bottom = new JPanel(); JButton refresh = new JButton("刷新"); JButton del = new JButton("删除选中"); bottom.add(refresh); bottom.add(del); add(bottom, BorderLayout.SOUTH); // 刷新按钮:重新查库并刷表格 refresh.addActionListener(e -> loadData()); // 删除按钮:取选中行的学号,调 DAO 删除后刷新 del.addActionListener(e -> { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(this, "请先选中一行"); return; } String sno = (String) model.getValueAt(row, 0); if (dao.delete(sno)) { loadData(); } }); loadData(); setVisible(true); } // 从数据库加载数据填充表格 private void loadData() { model.setRowCount(0); List<Student> list = dao.findAll(); for (Student s : list) { model.addRow(new Object[]{ s.getSno(), s.getName(), s.getSex(), s.getAge(), s.getScore() }); } } public static void main(String[] args) { new MainFrame(); } }

这段代码里loadData()是核心,每次增删改之后都调它重新查库刷新表格,保证界面和数据一致。删除前先判断有没有选中行,没选中就弹提示,这是最基本的健壮性处理。新增和修改可以再弹一个对话框收集输入,逻辑和删除类似,都是收集参数后调 DAO 再刷新。

3.4 编译运行命令

代码写完后,编译和运行都要带上驱动 jar 的类路径。

# 编译,-d 指定输出目录,-cp 引入驱动 javac -d out -cp "lib/mysql-connector-java-8.0.28.jar" src/entity/*.java src/util/*.java src/dao/*.java src/ui/*.java # 运行,Windows 下用分号分隔类路径 java -cp "out;lib/mysql-connector-java-8.0.28.jar" ui.MainFrame

Linux 或 macOS 下类路径分隔符是冒号,把分号换成冒号即可。运行起来能看到窗口、能刷新出数据、能删除,这个系统就算跑通了。

4. 实验报告怎么写才不像抄的:结构、图表和关键段落

4.1 报告骨架和每部分该放什么

实验报告不是代码堆砌,老师看的是你有没有理解自己写的东西。我一般建议按这个骨架组织:需求分析、系统设计、数据库设计、核心功能实现、测试与运行结果、问题与解决。需求分析写清楚系统要解决什么问题、有哪几类用户操作;系统设计画分层结构图,说明界面层、DAO 层、实体层各自职责;数据库设计给出建表语句和字段说明表;核心功能实现挑增删改查里最有代表性的贴代码加解释;测试部分给出运行截图和几条测试用例;问题与解决写你实际踩过的坑。

字段说明用表格比大段文字清楚得多,下面这种就够用。

字段名类型约束说明
snoVARCHAR(20)主键学号,唯一标识
nameVARCHAR(50)非空学生姓名
sexVARCHAR(4)可空性别
ageINT可空年龄
scoreDOUBLE可空成绩

4.2 把设计理由写进报告,而不是只贴代码

很多人报告里只有代码没有解释,这是最容易被扣分的地方。比如你用了PreparedStatement,就要写一句「相比 Statement 拼接字符串,PreparedStatement 通过占位符传参,能防止 SQL 注入,也避免了引号转义问题」。你用了分层,就要写「界面层不直接写 SQL,所有数据库操作集中在 DAO 层,便于维护和替换数据库」。这些解释才是报告区别于代码文件的价值。

再比如数据库连接为什么用工具类统一管理,可以写「连接参数集中在一处,修改数据库地址或密码时只需改一个文件,避免散落在各处导致遗漏」。这类话不用多,每个关键设计点配一两句,整份报告的专业度就上来了。

4.3 测试用例和运行结果怎么呈现

测试部分不要只放一张主界面截图就完事。至少覆盖新增、删除、修改、查询四类操作,每类给一条用例,写清楚输入、预期输出、实际结果。比如新增用例:输入学号 2024001、姓名张三、性别男、年龄 20、成绩 88.5,预期表格新增一行,实际结果一致。删除用例:选中 2024001 那行点删除,预期该行消失且数据库对应记录被删,实际结果一致。

截图建议截三张:主界面带数据、新增对话框、删除后的结果。截图下面配一句说明,不要只放图不说话。这样老师能顺着你的用例复现一遍,可信度比干巴巴的代码高很多。

5. 避坑与排查:那些让课设卡半天的常见问题

5.1 报 ClassNotFoundException: com.mysql.cj.jdbc.Driver

现象是运行时报找不到驱动类,程序直接崩。原因几乎都是编译或运行时没把驱动 jar 加进类路径,或者 jar 包版本和驱动类名对不上。MySQL 8.0 的驱动类名是com.mysql.cj.jdbc.Driver,5.x 是com.mysql.jdbc.Driver,写错了也会报这个错。解决办法是确认lib目录下有 jar 包,编译和运行的-cp参数都带上它,并且驱动类名和 jar 版本匹配。

5.2 中文姓名存进去变成问号

现象是界面输入中文,存到数据库里变成???。原因通常是建库时字符集没设成 utf8mb4,或者连接 URL 里没加characterEncoding=utf8。解决方法是建库语句带上DEFAULT CHARACTER SET utf8mb4,连接 URL 里补上characterEncoding=utf8,两个地方都对了中文就正常了。

5.3 时区报错 The server time zone value is unrecognized

现象是连接数据库时抛时区异常,提示服务器时区无法识别。原因是 MySQL 8.0 驱动对时区要求更严,而本地 MySQL 时区没配。最简单的解决办法是在连接 URL 后面加serverTimezone=UTC,一行参数就能解决,不用去改 MySQL 配置文件。

5.4 删除后表格没变化

现象是点了删除按钮,数据库里记录确实没了,但界面表格还显示着。原因是删除后没有重新查库刷新表格。解决办法是在删除成功后调用一次loadData(),重新从数据库拉数据填充表格。这个坑的本质是界面和数据是两份状态,任何写操作之后都要同步刷新。

5.5 学号重复插入导致主键冲突

现象是新增一个已存在的学号时程序报主键冲突异常。原因是学号设了主键,数据库不允许重复。解决办法是在新增前先查一次该学号是否存在,存在就弹提示不让插;或者捕获异常后给用户友好提示。课设里推荐前者,逻辑清晰也好写进报告。

6. 让课设更进一步的几个技巧

系统跑通、报告写完,如果还想拿更高分,可以在几个地方做增强。第一个是加模糊查询,按姓名关键字查学生,SQL 用LIKE配合PreparedStatement的%?%写法,界面加一个搜索框。第二个是加成绩统计,算平均分、最高分、最低分,用一条SELECT AVG(score),MAX(score),MIN(score) FROM student就能拿到,显示在界面底部。第三个是把数据库操作加上事务,比如批量导入学生时要么全成功要么全回滚,用conn.setAutoCommit(false)配合commit和rollback,报告里能体现你对事务的理解。

// 批量导入加事务,保证要么全成功要么全回滚 public boolean batchAdd(List<Student> list) { String sql = "INSERT INTO student(sno,name,sex,age,score) VALUES(?,?,?,?,?)"; Connection conn = null; try { conn = DBUtil.getConnection(); conn.setAutoCommit(false); // 关闭自动提交 try (PreparedStatement ps = conn.prepareStatement(sql)) { for (Student s : list) { ps.setString(1, s.getSno()); ps.setString(2, s.getName()); ps.setString(3, s.getSex()); ps.setInt(4, s.getAge()); ps.setDouble(5, s.getScore()); ps.addBatch(); // 加入批处理 } ps.executeBatch(); // 一次性执行 } conn.commit(); // 全部成功才提交 return true; } catch (Exception e) { try { if (conn != null) conn.rollback(); } catch (Exception ex) { ex.printStackTrace(); } e.printStackTrace(); return false; } finally { try { if (conn != null) conn.setAutoCommit(true); conn.close(); } catch (Exception e) { e.printStackTrace(); } } }

这段代码的关键是setAutoCommit(false)之后,所有插入要么一起commit,要么出错时rollback,不会出现导入一半失败留下脏数据的情况。批处理addBatch和executeBatch还能减少和数据库的交互次数,数据多的时候速度明显更快。

验证系统是否真的做对了,我有个习惯:把数据库里的数据全删掉,重启程序,看界面是不是空的;再新增几条,关掉程序重开,看数据还在不在。数据能持久化、界面能正确反映数据库状态,这个系统才算真的通了,而不是只在内存里自娱自乐。当年我第一次做课设就是没做这一步,演示时关了程序重开数据全没了,当场翻车。希望这些能帮到你。

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

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

SpringBoot+Vue+MySQL房屋租赁管理系统源码解析与部署指南

最近项目交流群里又有人在找一套能直接跑的房屋租赁管理系统源码&#xff0c;点名要SpringBoot后端加Vue前端加MySQL三件套&#xff0c;还说希望克隆下来就能启动。这类需求其实很典型&#xff1a;课程设计、小团队内部管理、个人项目练手&#xff0c;都需要一套结构清晰、业务…

作者头像 李华
网站建设 2026/10/20 4:39:29

5G网络架构深度解析:从核心网到接入网的关键技术

1. 5G网络架构到底在讲什么聊5G架构之前&#xff0c;先抛一个问题&#xff1a;为什么4G时代基站和核心网之间那套相对固定的连接方式&#xff0c;到了5G就非得推倒重来&#xff1f;这个问题我琢磨了很久&#xff0c;也跟不少做网络规划的朋友聊过&#xff0c;答案其实不复杂——…

作者头像 李华
网站建设 2026/10/20 4:39:04

Fusion 360个人版Python自动化:参数化建模与批量脚本实战

1. 先搞清楚&#xff1a;为什么 Autodesk 个人版限制一堆&#xff0c;却还能玩自动化Fusion 360 个人版&#xff08;个人使用授权&#xff09;这几年政策反复调整&#xff0c;很多人一看"非商业用途""收入门槛限制"就直接劝退了&#xff0c;觉得免费版就是…

作者头像 李华
网站建设 2026/10/20 4:38:42

Vibe Coding乱序根源与有序化工作流实战指南

1. 先说结论&#xff1a;Vibe Coding 乱在哪儿&#xff0c;Agent 解决不了什么过去的半年里&#xff0c;"Vibe Coding"从一个带有玩笑性质的词&#xff0c;慢慢变成了很多团队真实的工作方式。所谓 Vibe Coding&#xff0c;就是用自然语言描述意图&#xff0c;让 AI …

作者头像 李华
网站建设 2026/10/20 4:38:42

灵巧手实时触觉闭环控制:从转笔到精细操作的工程实践

1. 项目概述&#xff1a;这不是炫技&#xff0c;而是一次灵巧手控制范式的落地验证“WUJI Hand 2 机器灵巧手展示转笔技能&#xff0c;全套代码以 Apache 2.0 开源”——这个标题里藏着三个关键信号&#xff1a;硬件平台&#xff08;WUJI Hand 2&#xff09;、高动态操作任务&a…

作者头像 李华
网站建设 2026/10/20 4:38:31

sklearn Pipeline实战:避免数据泄漏与交叉验证陷阱

1. 为什么你的机器学习代码越写越乱刚入行做数据科学那会儿&#xff0c;我写过一个经典的“面条式”脚本&#xff1a;读数据、填缺失值、做独热编码、标准化、训练模型、评估&#xff0c;全部堆在一个两百多行的文件里。跑通一次之后&#xff0c;我想换个模型试试&#xff0c;结…

作者头像 李华