news 2026/10/28 4:02:40

Java学生信息管理系统实战:eclipse+MySQL+JDBC增删改查

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java学生信息管理系统实战:eclipse+MySQL+JDBC增删改查

简介:这套基于Eclipse和MySQL的Java学生信息管理系统,主要是为刚接触Java语言的开发者提供一份可以运行的练手项目,也适合作为课程设计或期末作业的参考。系统已经完成登录与注册模块,并按管理员、教师、学生三种身份分别设置操作权限:管理员和教师可以对学生信息进行增加、删除、修改、查询,学生账号只开放查询功能;系统还提供学生成绩信息的增删改查操作,这样能帮助初学者理解多角色权限控制和数据表结构设计。压缩包内一共包含四十四个文件,以十七个Java源文件和十八个Class编译文件为主,另有两个Jar依赖包和两个Zip源码包,以及工程配置文件和少量界面图片,整体大小约为六百一十六KB,压缩包按Eclipse工程结构整理,便于直接查看和阅读源码。目前已有六千四百七十四人学习下载,可见这套练手项目受到不少初学者关注。通过源码可以系统复习JDBC连接MySQL数据库、Swing界面布局、登录逻辑判断、不同角色菜单切换以及学生成绩信息管理的完整实现过程,适合想要把零散Java知识串联起来的初学者。

1. 期末前夜,最常被点名的那个 Java 课程设计

期末倒数第二周,很多人的任务清单里都会出现同一个题目:Java学生信息管理系统(eclipse+MySQL)。用大白话说,这是一个 Java Swing 桌面程序,通过 JDBC 连接本地 MySQL 数据库,对学生记录做增删改查。它不够新颖,甚至有点老派,却每年都出现在课程设计和毕设题库里,因为它刚刚好能把 Java 语法、SQL 语句、GUI 事件响应三样东西串成一条完整的链路。这套题目适合两类人:刚学完 Java 基础、想第一次做综合项目练手的新手,以及时间紧、需要尽快交付一个能现场演示成品的课程设计选手。别指望它有多高级,先把 JDBC 和 CRUD 跑通,后面接框架、做 Web 版都有底子。

2. 为什么是 eclipse + MySQL:先把选型逻辑说透

2.1 不是新技术不好,是你的交付场景选了它

每次做这个题都会有人问三个问题:为什么不用 IDEA?为什么不用 MyBatis?为什么不用 SQLite?答案不在技术偏好,而在你手头的环境。学校机房装的是 eclipse,教材和课件默认 Swing,数据库课讲的是 MySQL。你拿 IDEA 去机房答辩,先要解决 IDEA 能不能打开;拿 MyBatis 去讲,先要解释为什么框架比 JDBC 好。对课程设计来说,换工具和换框架都是在给自己增加没有必要的演示风险。

对比维度eclipse + MySQLIDEA + MyBatisSQLite / 纯文件
环境可用性机房普遍预装,开箱即用需要安装和激活,机房不一定有不依赖数据库服务,但体现不了数据库
课程匹配度与 Java 教材、数据库课一致与公司玩法一致,但与课程脱节无法解释数据落地过程
演示风险需要 MySQL 服务正常运行依赖 Maven 拉包,可能断网数据文件容易损坏且无 SQL 可言
答辩深度能讲 JDBC、SQL、事务能讲框架,但超出课程范围讲不出 SQL 与数据库设计

从这个表能看到,eclipse + MySQL 不是最优的工具组合,而是对你最稳的交付组合。评判课程设计看的不是技术栈新旧,而是流程是否完整:有建库脚本、有数据访问代码、有图形界面、能现场演示。这套组合每一步都是教材里教过的,答不上来的概率最低。

2.2 JDBC 与框架的边界:这个体量不需要上 MyBatis

网上大量 Spring Boot + MyBatis 版本的学生管理系统源码,为什么还建议手写 JDBC?因为题目明确写了 eclipse + MySQL,暗示界面是 Swing,数据访问用手写 JDBC。项目里只有一张 student 表,JDBC 代码量在 100 行上下,写起来不复杂;换成 MyBatis,要引入一堆依赖、写 mapper 接口和 XML,还要面对 Maven 下载失败、实体类与数据库字段映射不一致这些问题。这些不是能力问题,是环境问题。

我一般会把代码分成三层:实体类 Student 只管字段;DAO 类只写 SQL 访问;界面类只处理按钮和表格。分层的实际好处有两个:第一,数据库换库或者改字段时只动 DAO;第二,答辩老师问"你这系统的结构是什么"时,你能用三句话讲清楚。单表 CRUD 没必要加 Service 层,加了反而会被追问"这一层解决了什么问题"。

2.3 先建库建表:student 表怎么设计才经得起演示

动手写 Java 之前,先把数据库立起来。这个系统保存的学生数据通常就一张表,字段按课程设计常见的范围来:学号、姓名、性别、年龄、班级、电话,再加一个自增主键和创建时间。字段别贪多,答辩现场要能解释每个字段为什么这么设。

CREATE DATABASE IF NOT EXISTS school_db DEFAULT CHARSET utf8mb4; USE school_db; CREATE TABLE student ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '自增主键', student_no VARCHAR(20) NOT NULL UNIQUE COMMENT '学号,唯一约束防止重复录入', name VARCHAR(50) NOT NULL COMMENT '姓名', gender VARCHAR(10) DEFAULT '男' COMMENT '性别', age INT COMMENT '年龄,不做范围约束,留给界面层控制', class_name VARCHAR(50) COMMENT '班级名称', phone VARCHAR(20) COMMENT '电话用 varchar 保存,保留前导零', create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间,方便排序' ) ENGINE=InnoDB COMMENT='学生信息表';

这段 SQL 里,student_no 加 UNIQUE 是关键:真实录入场景中学号是业务主键,重复学号会让数据没意义。phone 用 VARCHAR 而不是 BIGINT,因为手机号可能以 0 开头,数字类型会丢掉前导零。class_name 故意不用 class 做字段名,class 是 SQL 里的关键字,容易在拼接语句时触发语法错误。ENGINE 指定 InnoDB,是为了后面如果需要事务处理时不会被 MyISAM 卡住。

演示数据也建议写成脚本,而不是在界面上一条条手输:

INSERT INTO student (student_no, name, gender, age, class_name, phone) VALUES ('2024001', '张伟', '男', 20, '软件2301', '13800000001'), ('2024002', '李娜', '女', 21, '软件2302', '13900000002'), ('2024003', '王强', '男', 19, '大数据2301', '13700000003');

注意:演示前一定要有一两条中文数据。很多翻车现场是数据库里空表,界面点查询只看到一行列名,评委看不到效果。

3. eclipse 里把项目和 MySQL 拉通:从建工程到第一条查询

3.1 建 Java 工程与 WindowBuilder:界面用手拖还是手写

如果 eclipse 是刚装的,先做两件事:确认 JDK 和 WindowBuilder 插件。JDK 不是装得越高越好,课程设计常用 JDK 8,因为大部分机房和教材都基于它。eclipse 安装教程通常只说"解压即用",但打开后报缺少 JRE 或 JDK,多半是系统的 Path 里没配好 JAVA_HOME。这个坑不用慌,在 eclipse.ini 里指定 -vm 指向 JDK 的 javaw.exe 也可以。

WindowBuilder 是用来拖 Swing 界面的插件,装了它,新建 Swing 窗体时可以直接拖 JLabel、JTextField、JButton,自动生成代码。手写 Swing 也完全可以,前提是你清楚 BorderLayout、GridLayout 的区别。我的建议是:课程设计时间紧就装 WindowBuilder,拖完窗口再手动改事件代码;纯手写容易在布局上耗掉大量时间,得不偿失。

新建工程的步骤是:File -> New -> Java Project,Project name 填 StudentManager,JRE 选你本机装的 JDK 8,点 Finish。然后在 src 下新建三个包:com.school.model(实体类)、com.school.dao(数据访问)、com.school.ui(界面和启动入口)。包名虽然不是必须,但能让答辩老师一眼看懂分层。

3.2 引入 MySQL 驱动:jar 包放对位置,连接才能通

JDBC 连接 MySQL 必须有一个驱动 jar,也就是 mysql-connector-java。常见做法是去 Maven 中央仓库或 MySQL 官网下载对应 jar,下载后不要直接塞进 JDK 的扩展目录,而是在项目根目录新建 lib 文件夹,把 jar 放进去,再右键项目 -> Build Path -> Add to Build Path。看到 jar 出现在 Referenced Libraries 里才算引入成功。

驱动版本有讲究。MySQL 5.7 用 5.1.49 或 8.0.x 驱动都可以;MySQL 8.0 必须用 8.0.x 驱动,并且驱动类名从 com.mysql.jdbc.Driver 变成了 com.mysql.cj.jdbc.Driver。这个差异是新手最容易翻车的点,后面避坑章会单独讲。连接数据库的 URL 也不是写个 jdbc:mysql://localhost:3306/school_db 就能跑,MySQL 8 还要处理 SSL 和时区。把这些配置集中放到一个工具类里,是后续所有功能的基础。

package com.school.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBUtil { private static final String DRIVER = "com.mysql.cj.jdbc.Driver"; private static final String URL = "jdbc:mysql://localhost:3306/school_db" + "?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8"; private static final String USER = "root"; private static final String PASSWORD = "123456"; static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { throw new ExceptionInInitializerError("驱动加载失败,检查 jar 是否引入 Build Path"); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }

代码里最关键的是 static 块中的 Class.forName(DRIVER):它把驱动类加载进 JVM,并注册到 DriverManager。MySQL 8 的驱动类改成 com.mysql.cj.jdbc.Driver 后,旧写法 com.mysql.jdbc.Driver 会直接抛 ClassNotFoundException。URL 上的 useSSL=false 是为了避免本地开发时 TLS 握手告警;serverTimezone=Asia/Shanghai 是针对 MySQL 8 的时区要求;characterEncoding=utf8 配合建库时的 utf8mb4,才能避免中文字符乱码。

单独跑一次连接测试,确认这步没问题再写界面:

package com.school.util; import java.sql.Connection; public class DBUtilTest { public static void main(String[] args) { try (Connection conn = DBUtil.getConnection()) { System.out.println("连接成功,当前数据库:" + conn.getCatalog()); } catch (Exception e) { e.printStackTrace(); } } }

这里用了 try-with-resources 语法,JDK 8 开始支持。Connection 是资源,finally 里手动 close 容易忘,用这个语法结束后会自动归还连接。如果控制台打印"连接成功,当前数据库:school_db",说明驱动、URL、账号密码都对了,后面所有 DAO 代码只需要复用 getConnection()。

3.3 最小可运行窗口:先别急着写功能,把骨架跑起来

数据库通了,接下来建一个最小窗口,保证项目能从 eclipse 里直接运行。这一步的目的是尽早排除"找不到或无法加载主类"这类运行环境问题,而不是憋到最后再启动。

package com.school.ui; import javax.swing.*; public class MainFrame extends JFrame { public MainFrame() { setTitle("学生信息管理系统"); setSize(800, 600); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> { MainFrame frame = new MainFrame(); frame.setVisible(true); }); } }

代码里有两个习惯值得提:setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) 保证点关闭按钮时进程退出,否则 eclipse 的控制台会一直挂着红色停止按钮;SwingUtilities.invokeLater 把界面创建丢到事件分发线程,避免多线程下的界面绘制问题。现在直接在 eclipse 里右键 Run As -> Java Application,能看到一个空白窗口。窗口起来后,再把上一节 DBUtilTest 的 main 方法内容临时搬进来验证,整个运行链路就通了。

4. 跑通增删改查:实体、DAO 与界面三件套

4.1 实体类:字段和数据库表一一对应

实体类 Student 是数据库表和界面之间的数据载体。字段名尽量和数据库列保持一致,类型要匹配:age 是 INT 就用 Integer,id 是自增主键也用 Integer 包装类而不是 int,这样查询结果为空时不会因为自动拆箱而抛 NullPointerException。

package com.school.model; public class Student { private Integer id; private String studentNo; private String name; private String gender; private Integer age; private String className; private String phone; public Student() { } public Student(String studentNo, String name, String gender, Integer age, String className, String phone) { this.studentNo = studentNo; this.name = name; this.gender = gender; this.age = age; this.className = className; this.phone = phone; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } // 其余 getter/setter 由 eclipse 自动生成 }

写这个类时注意两点。第一,必须保留无参构造,JTable 的 DefaultTableModel 和很多工具默认依赖它;第二,getter/setter 别手写,eclipse 里用右键 Source -> Generate Getters and Setters 生成,减少低级错误。课程设计里日期字段统一用 String 在界面展示,不在实体里引入 java.util.Date,能省掉一堆 SimpleDateFormat 转换的麻烦。

4.2 DAO 层:PreparedStatement 是唯一推荐写法

DAO 层是连接数据库的全部代码,也是答辩时最会被问的部分。所有查询参数都通过 PreparedStatement 绑定,不要用 Statement 拼字符串,这是安全底线,也是面试里经常被提到的话题:SQL 注入是怎么发生的。

package com.school.dao; import com.school.model.Student; import com.school.util.DBUtil; import java.sql.*; import java.util.ArrayList; import java.util.List; public class StudentDao { public int add(Student stu) { String sql = "INSERT INTO student (student_no, name, gender, age, class_name, phone) " + "VALUES (?, ?, ?, ?, ?, ?)"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, stu.getStudentNo()); ps.setString(2, stu.getName()); ps.setString(3, stu.getGender()); ps.setInt(4, stu.getAge()); ps.setString(5, stu.getClassName()); ps.setString(6, stu.getPhone()); return ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); return 0; } } public int delete(Integer id) { String sql = "DELETE FROM student WHERE id = ?"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setInt(1, id); return ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); return 0; } } public int update(Student stu) { String sql = "UPDATE student SET student_no=?, name=?, gender=?, age=?, class_name=?, phone=? " + "WHERE id=?"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, stu.getStudentNo()); ps.setString(2, stu.getName()); ps.setString(3, stu.getGender()); ps.setInt(4, stu.getAge()); ps.setString(5, stu.getClassName()); ps.setString(6, stu.getPhone()); ps.setInt(7, stu.getId()); return ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); return 0; } } public List<Student> search(String keyword) { String sql = "SELECT * FROM student WHERE student_no LIKE ? " + "OR name LIKE ? OR class_name LIKE ? ORDER BY id"; List<Student> list = new ArrayList<>(); String like = "%" + keyword + "%"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, like); ps.setString(2, like); ps.setString(3, like); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) { Student stu = new Student(); stu.setId(rs.getInt("id")); stu.setStudentNo(rs.getString("student_no")); stu.setName(rs.getString("name")); stu.setGender(rs.getString("gender")); stu.setAge(rs.getInt("age")); stu.setClassName(rs.getString("class_name")); stu.setPhone(rs.getString("phone")); list.add(stu); } } } catch (SQLException e) { e.printStackTrace(); } return list; } }

这段代码有几个关键约定。第一,所有 SQL 里的问号占位符都要按顺序 set 参数,参数下标从 1 开始,顺序错了数据就会串到别的字段。第二,executeUpdate 返回受影响行数,增删改都靠它判断是否成功;search 方法用 ResultSet 逐行读取,然后封装成 Student 对象。第三,LIKE 的百分号在 Java 端拼好再传给 PreparedStatement,不要在 SQL 里写死,否则关键字为空时会查不到数据。ORDER BY id 保证每次查询结果顺序稳定,演示时不至于数据乱跳。

4.3 界面联动:JTable 填数据和按钮事件

界面层最核心的是把 DAO 返回的 List 变成 JTable 的行。JTable 的构造函数接受 DefaultTableModel,通过 model.setRowCount(0) 清空旧数据,再逐行 addRow,实现"刷新表格"。

package com.school.ui; import com.school.dao.StudentDao; import com.school.model.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 tableModel; private JTextField keywordField; private StudentDao dao = new StudentDao(); public MainFrame() { initUI(); refresh(dao.search("")); } private void initUI() { setTitle("学生信息管理系统"); setSize(800, 600); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new BorderLayout()); JPanel topPanel = new JPanel(); keywordField = new JTextField(15); JButton searchBtn = new JButton("查询"); searchBtn.addActionListener(e -> refresh(dao.search(keywordField.getText().trim()))); topPanel.add(keywordField); topPanel.add(searchBtn); add(topPanel, BorderLayout.NORTH); String[] columns = {"ID", "学号", "姓名", "性别", "年龄", "班级", "电话"}; tableModel = new DefaultTableModel(columns, 0); table = new JTable(tableModel); add(new JScrollPane(table), BorderLayout.CENTER); JPanel bottomPanel = new JPanel(); JButton addBtn = new JButton("新增"); JButton updateBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); bottomPanel.add(addBtn); bottomPanel.add(updateBtn); bottomPanel.add(deleteBtn); add(bottomPanel, BorderLayout.SOUTH); } private void refresh(List<Student> list) { tableModel.setRowCount(0); for (Student stu : list) { tableModel.addRow(new Object[]{ stu.getId(), stu.getStudentNo(), stu.getName(), stu.getGender(), stu.getAge(), stu.getClassName(), stu.getPhone() }); } } }

这段代码体现了三个约定俗成的做法。第一,JTable 不用 List 直接展示,而是通过 DefaultTableModel 中转,model 负责管理列名和行数据;第二,查询按钮的 ActionListener 里重新调用 dao.search,实现查完立刻刷新表格;第三,新增、修改、删除按钮的事件里要先从表格选中行拿主键 id,再调 DAO,最后 refresh。没有这套联动,数据改了界面不更新,是最常见的"界面死板"扣分点。

删除按钮的代码套路是取选中行、拿值、调 DAO、刷新:

deleteBtn.addActionListener(e -> { int row = table.getSelectedRow(); if (row < 0) { JOptionPane.showMessageDialog(this, "请先选中一行"); return; } int confirm = JOptionPane.showConfirmDialog(this, "确定删除这条记录?", "确认", JOptionPane.YES_NO_OPTION); if (confirm == JOptionPane.YES_OPTION) { int id = (Integer) tableModel.getValueAt(row, 0); if (dao.delete(id) > 0) { refresh(dao.search("")); } } });

getSelectedRow 返回的是视图行索引,直接用没问题;getValueAt(row, 0) 取的是 ID 这一列,所以 columns 数组的顺序不能乱。新增和修改按钮本质上是弹出一组 JTextField 再组装 Student 对象,逻辑比删除还简单,这里不再重复。MainFrame 的启动入口沿用上一章的写法,把 main 方法保留即可。

5. 避坑:eclipse + MySQL 最容易翻车的 5 个现场

5.1 eclipse 找不到或无法加载主类

现象:右键 Run As -> Java Application 时弹窗或控制台报"找不到或无法加载主类 org.apache.catalina.startup.bootstrap",或者直接说找不到主类。

原因:两类最常见。一类是 workspace 里存在旧的 Tomcat 启动配置,eclipse 记住了上次的运行目标;另一类是 Main 类带 main 方法但签名不对,比如少了 static,或者类没有编译到 bin 目录。

解决:先删掉 Run Configurations 里的旧启动项,然后 Project -> Clean 重新编译,确认 main 方法签名是 public static void main(String[] args)。如果还不行,右键项目 -> Properties -> Java Build Path,检查输出目录是否指向 bin。

5.2 MySQL 服务启动失败:net start mysql 报错

现象:cmd 里执行 net start mysql,提示"服务名无效",或"服务正在启动…服务无法控制";eclipse 连数据库时报 Communications link failure。

原因:多数人按 mysql 安装教程装完后,没有用管理员权限执行初始化,data 目录为空或权限不对;另一种是端口 3306 被之前没关干净的进程占用。

解决:以管理员身份打开 cmd,先执行 mysqld --initialize-insecure --basedir=你的安装路径 --datadir=你的数据目录,再 net start mysql。如果端口占用,netstat -ano | findstr 3306 查 PID,在任务管理器里结束对应进程。MySQL 8 的安装流程和 5.7 不一样,照着对应版本教程装,别混用。

5.3 Public Key Retrieval is not allowed 与 Access denied

现象:连接测试报 java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed,或者 Access denied for user 'root'@'localhost'。

原因:MySQL 8 默认认证方式是 caching_sha2_password,驱动连接时默认不获取服务器公钥;Access denied 则是密码填错或者 root 用户只允许 localhost 登录。

解决:URL 上追加 allowPublicKeyRetrieval=true,和 useSSL=false 一起用。Access denied 就确认密码和用户名,MySQL 8 初始 root 密码为空,如果安装时设过密码,记得改掉 DBUtil 里的常量。课程设计里把密码硬编码在工具类没问题,但答辩时可以主动说正式项目会放到配置文件,这是加分句。

5.4 中文乱码:界面上全是问号

现象:窗口里姓名显示成"??"或"张??",数据库表里看也是乱码,或者界面正常但数据库乱码。

原因:连接 URL 缺 characterEncoding=utf8;建库时没指定 utf8mb4,库表继承了 latin1;eclipse 工作空间的文本编码不是 UTF-8。

解决:三层对齐。建库语句用 DEFAULT CHARSET utf8mb4,URL 尾部加 characterEncoding=utf8,eclipse 里 Window -> Preferences -> General -> Workspace,把 Text file encoding 改成 UTF-8。MySQL 的 my.ini 里 character-set-server 也建议设成 utf8mb4,改完重启服务。

5.5 ClassNotFoundException: com.mysql.jdbc.Driver

现象:DBUtil 的 static 块抛 ClassNotFoundException,异常消息里写的是 com.mysql.jdbc.Driver。

原因:MySQL 8 换了新驱动类名,旧类名在新版驱动里被移除了;或者 jar 没被加入 Build Path,在 lib 文件夹里躺着但没有 Add to Build Path。

解决:把驱动常量统一改成 com.mysql.cj.jdbc.Driver,MySQL 5.7 用 8.0.x 驱动时也能用这个类名。第二个原因更隐蔽:eclipse 里 jar 在磁盘上存在并不代表它在编译路径里,必须右键项目 -> Build Path -> Configure Build Path,在 Libraries 里看到该 jar。很多人放了 jar 还报类找不到,最后发现是没 Add。

这五个现场是每届学生系统里出现频率最高的。避坑思路其实都一样:先分清楚是环境问题、驱动问题还是代码问题,再按层排查,不要改一行代码就跑一次调试。MySQL 的安装和配置占了不稳定因素的大头,把服务启动、编码、认证这三座山搬掉,代码本身反而很少出幺蛾子。

6. 让它更像一个能演示的成品:五个加分细节与我的收尾习惯

功能做完,离"能演示"还差几步。第一个加分细节是把数据库配置抽到 db.properties 文件里,这是课程设计里最容易被单独表扬的设计。在 src 下新建 db.properties,写入 driver、url、username、password 四行,DBUtil 改成用 Properties 类加载,今后换数据库或改密码不用重编译。

package com.school.util; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; public class DBUtil { private static String DRIVER; private static String URL; private static String USER; private static String PASSWORD; static { try (InputStream in = DBUtil.class.getClassLoader() .getResourceAsStream("db.properties")) { Properties props = new Properties(); props.load(in); DRIVER = props.getProperty("driver"); URL = props.getProperty("url"); USER = props.getProperty("username"); PASSWORD = props.getProperty("password"); Class.forName(DRIVER); } catch (Exception e) { throw new ExceptionInInitializerError("配置加载失败"); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }

这段改造把连接参数从编译期常量变成运行时读取,配置和代码分离。第二个细节是给查询框加回车监听,JTextField 注册 ActionListener 后按回车同样触发查询,演示时不用特意去点按钮,动作更顺。第三个细节是底部加一行"共 N 条记录",直接用 search 返回的 list.size() 就能显示,数据量一眼可见。第四个细节是准备一份演示话术:先查全部、再模糊查询一个名字、改一条、删一条、最后重新查询,顺序正好覆盖五个功能。第五个细节是备份好建库 SQL 和演示数据 SQL,脚本才是复活的本钱。

我自己每次交付前不先点"运行",而是先去 Windows 服务里看一眼 MySQL 有没有启动,再用命令行测试一次 DBUtil 连接,最后才打开界面。因为课程设计答辩那天第一个黑匣子就是数据库服务,它没起,代码写得再对也是 100 分变 60 分。另一条血泪经验是:演示用的数据库一定要用建库脚本现场重建过的,别在答辩前临时改表结构,已经填好的数据会全部失效。希望这个项目里走的弯路你少走一遍,希望帮到你。

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

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

隔离内网AI Agent工程实战:本地模型+MCP+Skills+SQLite+Vue全栈落地

1. 隔离内网下的 AI Agent 工程&#xff0c;到底难在哪 先说说我为什么会碰这个题目。去年下半年开始&#xff0c;团队里陆续有人尝试用 AI Agent 做一些内部工具的自动化&#xff0c;比如自动整理工单、自动生成周报、自动跑数据核对。一开始大家都是在能连外网的开发机上玩&a…

作者头像 李华
网站建设 2026/10/15 22:38:09

chrome-devtools-mcp:AI直连浏览器DevTools协议的MCP适配层

1. 项目概述&#xff1a;这不是一个插件&#xff0c;而是一次浏览器与AI的“神经直连”“chrome-devtools-mcp”——光看这个名字&#xff0c;很多人第一反应是“又一个Chrome扩展&#xff1f;”&#xff0c;或者下意识联想到那些在chrome://extensions/里点几下就能装上的小工…

作者头像 李华
网站建设 2026/10/17 22:56:06

云豹直播系统开源版:PHP直播源码三端架构、部署与二次开发实战

简介&#xff1a;云豹直播系统开源版是一套以PHP为核心的完整直播平台源码&#xff0c;面向希望搭建、运营直播平台或进行二次开发的个人开发者与中小企业。ZIP压缩包共121.37MB&#xff0c;包含2001个文件&#xff0c;其中JavaScript文件868个、Java文件278个、XML文件237个、…

作者头像 李华
网站建设 2026/10/27 6:12:49

全能截图工具实测:长截图、OCR、录屏一体的效率工作流

上周整理一份项目复盘报告时&#xff0c;我发现自己正陷入一个极其荒诞的工作流&#xff1a;需要滚动长截图时打开A软件&#xff0c;需要贴图对照时切到B工具&#xff0c;OCR识别合同关键字段要单独开C程序&#xff0c;最后补录一段操作演示又得掏出D应用。一台电脑上光是"…

作者头像 李华
网站建设 2026/10/14 7:46:11

AI芯片软硬件协同设计:脉动阵列原理与Transformer硬件映射实战

AI 芯片这个话题&#xff0c;聊架构、聊算力、聊制程的文章已经够多了&#xff0c;但真正落到"软硬件怎么配合设计"这个层面&#xff0c;能讲清楚的人并不多。我做了几年加速器相关的软硬件协同工作&#xff0c;从 RTL 仿真到编译器算子映射都趟过一遍&#xff0c;深…

作者头像 李华
网站建设 2026/10/15 16:37:51

蓝牙Provision技术详解:概念、协议流程与ESP32入网实战排查

1. Provision到底是什么&#xff1a;从配对到入网&#xff0c;一次说清 这是蓝牙学习系列的第三篇。前两篇我分别聊了蓝牙协议栈的基本分层&#xff0c;以及一条经典蓝牙连接从寻呼到建链的完整状态机&#xff0c;算是把“链路怎么通”这件事讲透了。这一篇要聊的是Provision。…

作者头像 李华