拜托 别再搞逻辑删除了

拜托 别再搞逻辑删除了

基于领导的一句话:”产生的数据都是有价值的数据“,因此第一个想到的就是假删(”逻辑删除“),还将其定义为了一个标准,所有表都要有 逻辑删除字段is_validate。从此开始了我不幸的人生

  1. 自从有了逻辑删除,唯一索引再也与我没有了缘分
  2. 自从有了逻辑删除,所有的单表查询,连接查询,更新,带where的我都得带上他
  3. 自从有了逻辑删除,我再也分不清别人设计的表是一对一,一对多,还是多对多,还是劳什子结构
  4. 自从有了逻辑删除,测试小伙伴就多了一个测试用例,希望她们能测试覆盖到所有操作
  5. 自从有了逻辑删除,并发场景或者网络重试等,完全依赖于代码中的锁,希望大家的代码能锁得住,保证得了数据的完整性

设计逻辑删除的人,我不信他是编码的人

请确保自己的业务真要逻辑删除,即使真要逻辑删除,也别在我的业务表里瞎参合
好鸡蛋和坏鸡蛋,统统放在一个篮子里,让我傻傻分不清楚,剪不断,理还乱

如果业务真要逻辑删除,可以考虑

  1. 通过Mysql trigger对delete事件进行监听,转换到_del表中
  2. 通过Canal等开源项目对binlog进行监听,转存到其他地方
好的!我们继续完成剩余的 **3 个管理面板**:`CourseManagementPanel`、`ClassManagementPanel` 和 `EnrollmentManagementPanel`,全部基于你已实现的 DAO 层与数据库结构,支持完整的 **增删改查(CRUD)功能**,并使用 `JTable + 表单输入 + 按钮操作` 的标准 Swing 模式。 --- ## ✅ 前提说明 - 所有 DAO 已存在(如 `CourseDaoImpl`, `SchoolClassDaoImpl`, `EnrollmentDaoImpl`) - 实体类已定义 - 使用 `DefaultTableModel` 动态更新表格 - 支持:添加、修改、删除、刷新、回填、清空 - 字段与数据库严格对齐 --- # ✅ 3. 课程管理面板:`CourseManagementPanel.java` ```java // gui/CourseManagementPanel.java package gui; import dao.CourseDao; import dao.impl.CourseDaoImpl; import entity.Course; import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.util.List; public class CourseManagementPanel extends JPanel { private final CourseDao courseDao = new CourseDaoImpl(); private final DefaultTableModel model = new DefaultTableModel( new String[]{"课程代码", "名称", "学分", "类型", "教师ID", "学期", "周学时", "最大人数", "部门", "描述"}, 0); private final JTable table = new JTable(model); private final JTextField txtCode = new JTextField(10); private final JTextField txtName = new JTextField(15); private final JTextField txtCredits = new JTextField(5); private final JTextField txtType = new JTextField(8); private final JTextField txtTeacherId = new JTextField(8); private final JTextField txtSemester = new JTextField(10); private final JTextField txtHours = new JTextField(5); private final JTextField txtMaxStudents = new JTextField(5); private final JTextField txtDept = new JTextField(12); private final JTextField txtDesc = new JTextField(20); public CourseManagementPanel() { setLayout(new BorderLayout()); loadCourses(); add(new JScrollPane(table), BorderLayout.CENTER); // 表单布局 JPanel form = new JPanel(new GridLayout(4, 5, 10, 10)); form.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); form.add(new JLabel("课程代码:", SwingConstants.RIGHT)); form.add(txtCode); form.add(new JLabel("名称:", SwingConstants.RIGHT)); form.add(txtName); form.add(new JLabel("学分:", SwingConstants.RIGHT)); form.add(txtCredits); form.add(new JLabel("类型:", SwingConstants.RIGHT)); form.add(txtType); form.add(new JLabel("教师ID:", SwingConstants.RIGHT)); form.add(txtTeacherId); form.add(new JLabel("学期:", SwingConstants.RIGHT)); form.add(txtSemester); form.add(new JLabel("周学时:", SwingConstants.RIGHT)); form.add(txtHours); form.add(new JLabel("最大人数:", SwingConstants.RIGHT)); form.add(txtMaxStudents); form.add(new JLabel("部门:", SwingConstants.RIGHT)); form.add(txtDept); form.add(new JLabel("描述:", SwingConstants.RIGHT)); form.add(txtDesc); JButton btnAdd = new JButton("添加"); JButton btnUpdate = new JButton("修改"); JButton btnDelete = new JButton("删除"); JButton btnRefresh = new JButton("刷新"); JButton btnClear = new JButton("清空"); JPanel btnPanel = new JPanel(); btnPanel.add(btnAdd); btnPanel.add(btnUpdate); btnPanel.add(btnDelete); btnPanel.add(btnRefresh); btnPanel.add(btnClear); form.add(btnPanel); add(form, BorderLayout.SOUTH); // 事件绑定 btnAdd.addActionListener(e -> addCourse()); btnUpdate.addActionListener(e -> updateCourse()); btnDelete.addActionListener(e -> deleteCourse()); btnRefresh.addActionListener(e -> refreshTable()); btnClear.addActionListener(e -> clearForm()); table.getSelectionModel().addListSelectionListener(evt -> { if (!evt.getValueIsAdjusting()) fillFormFromTable(); }); } private void loadCourses() { try { List<Course> courses = courseDao.getAllCourses(); for (Course c : courses) { model.addRow(new Object[]{ c.getCourseCode(), c.getName(), c.getCredits(), c.getType(), c.getTeacherId(), c.getSemester(), c.getWeeklyHours(), c.getMaxStudents(), c.getDepartment(), c.getDescription() }); } } catch (Exception e) { JOptionPane.showMessageDialog(this, "加载课程失败:" + e.getMessage()); } } private void addCourse() { try { Course c = new Course(); c.setCourseCode(txtCode.getText().trim()); c.setName(txtName.getText().trim()); c.setCredits(Integer.parseInt(txtCredits.getText())); c.setType(txtType.getText().trim()); c.setTeacherId(Integer.parseInt(txtTeacherId.getText())); c.setSemester(txtSemester.getText().trim()); c.setWeeklyHours(Integer.parseInt(txtHours.getText())); c.setMaxStudents(Integer.parseInt(txtMaxStudents.getText())); c.setDepartment(txtDept.getText().trim()); c.setDescription(txtDesc.getText().trim()); courseDao.insertCourse(c); model.addRow(new Object[]{ c.getCourseCode(), c.getName(), c.getCredits(), c.getType(), c.getTeacherId(), c.getSemester(), c.getWeeklyHours(), c.getMaxStudents(), c.getDepartment(), c.getDescription() }); JOptionPane.showMessageDialog(this, "✅ 添加成功!"); clearForm(); } catch (Exception e) { JOptionPane.showMessageDialog(this, "❌ 添加失败:" + e.getMessage()); } } private void updateCourse() { int row = table.getSelectedRow(); if (row < 0) { JOptionPane.showMessageDialog(this, "请先选择一门课程!"); return; } try { Course c = new Course(); c.setCourseCode(txtCode.getText().trim()); c.setName(txtName.getText().trim()); c.setCredits(Integer.parseInt(txtCredits.getText())); c.setType(txtType.getText().trim()); c.setTeacherId(Integer.parseInt(txtTeacherId.getText())); c.setSemester(txtSemester.getText().trim()); c.setWeeklyHours(Integer.parseInt(txtHours.getText())); c.setMaxStudents(Integer.parseInt(txtMaxStudents.getText())); c.setDepartment(txtDept.getText().trim()); c.setDescription(txtDesc.getText().trim()); courseDao.updateCourse(c); model.setValueAt(c.getName(), row, 1); model.setValueAt(c.getCredits(), row, 2); model.setValueAt(c.getType(), row, 3); model.setValueAt(c.getTeacherId(), row, 4); model.setValueAt(c.getSemester(), row, 5); model.setValueAt(c.getWeeklyHours(), row, 6); model.setValueAt(c.getMaxStudents(), row, 7); model.setValueAt(c.getDepartment(), row, 8); model.setValueAt(c.getDescription(), row, 9); JOptionPane.showMessageDialog(this, "✅ 修改成功!"); } catch (Exception e) { JOptionPane.showMessageDialog(this, "❌ 修改失败:" + e.getMessage()); } } private void deleteCourse() { int row = table.getSelectedRow(); if (row < 0) return; String code = (String) model.getValueAt(row, 0); int confirm = JOptionPane.showConfirmDialog(this, "确定删除课程 " + code + "?"); if (confirm != JOptionPane.YES_OPTION) return; try { courseDao.deleteCourse(code); model.removeRow(row); JOptionPane.showMessageDialog(this, "✅ 删除成功!"); } catch (Exception e) { JOptionPane.showMessageDialog(this, "❌ 删除失败:" + e.getMessage()); } } private void refreshTable() { model.setRowCount(0); loadCourses(); } private void fillFormFromTable() { int row = table.getSelectedRow(); if (row < 0) return; txtCode.setText(model.getValueAt(row, 0).toString()); txtName.setText(model.getValueAt(row, 1).toString()); txtCredits.setText(model.getValueAt(row, 2).toString()); txtType.setText(model.getValueAt(row, 3).toString()); txtTeacherId.setText(model.getValueAt(row, 4).toString()); txtSemester.setText(model.getValueAt(row, 5).toString()); txtHours.setText(model.getValueAt(row, 6).toString()); txtMaxStudents.setText(model.getValueAt(row, 7).toString()); txtDept.setText(model.getValueAt(row, 8).toString()); txtDesc.setText(model.getValueAt(row, 9).toString()); } private void clearForm() { txtCode.setText(""); txtName.setText(""); txtCredits.setText(""); txtType.setText(""); txtTeacherId.setText(""); txtSemester.setText(""); txtHours.setText(""); txtMaxStudents.setText(""); txtDept.setText(""); txtDesc.setText(""); } } ``` --- # ✅ 4. 班级管理面板:`ClassManagementPanel.java` ```java // gui/ClassManagementPanel.java package gui; import dao.SchoolClassDao; import dao.impl.SchoolClassDaoImpl; import entity.SchoolClass; import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.util.Date; import java.sql.Date; public class ClassManagementPanel extends JPanel { private final SchoolClassDao classDao = new SchoolClassDaoImpl(); private final DefaultTableModel model = new DefaultTableModel( new String[]{"ID", "班级名", "年级", "班主任ID", "入学年份", "专业", "部门", "当前人数", "最大容量", "创建时间", "状态"}, 0); private final JTable table = new JTable(model); private final JTextField txtId = new JTextField(8); private final JTextField txtClassName = new JTextField(12); private final JTextField txtGrade = new JTextField(8); private final JTextField txtTeacherId = new JTextField(8); private final JTextField txtYear = new JTextField(8); private final JTextField txtMajor = new JTextField(12); private final JTextField txtDept = new JTextField(12); private final JTextField txtCount = new JTextField(8); private final JTextField txtCap = new JTextField(8); private final JTextField txtCreatedAt = new JTextField(12); // YYYY-MM-DD private final JCheckBox chkActive = new JCheckBox("启用", true); public ClassManagementPanel() { setLayout(new BorderLayout()); loadClasses(); add(new JScrollPane(table), BorderLayout.CENTER); JPanel form = new JPanel(new GridLayout(4, 5, 10, 10)); form.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); form.add(new JLabel("ID:", SwingConstants.RIGHT)); form.add(txtId); form.add(new JLabel("班级名:", SwingConstants.RIGHT)); form.add(txtClassName); form.add(new JLabel("年级:", SwingConstants.RIGHT)); form.add(txtGrade); form.add(new JLabel("班主任ID:", SwingConstants.RIGHT)); form.add(txtTeacherId); form.add(new JLabel("入学年份:", SwingConstants.RIGHT)); form.add(txtYear); form.add(new JLabel("专业:", SwingConstants.RIGHT)); form.add(txtMajor); form.add(new JLabel("部门:", SwingConstants.RIGHT)); form.add(txtDept); form.add(new JLabel("当前人数:", SwingConstants.RIGHT)); form.add(txtCount); form.add(new JLabel("最大容量:", SwingConstants.RIGHT)); form.add(txtCap); form.add(new JLabel("创建时间:", SwingConstants.RIGHT)); form.add(txtCreatedAt); form.add(new JLabel("状态:", SwingConstants.RIGHT)); form.add(chkActive); JButton btnAdd = new JButton("添加"); JButton btnUpdate = new JButton("修改"); JButton btnDelete = new JButton("删除"); JButton btnRefresh = new JButton("刷新"); JButton btnClear = new JButton("清空"); JPanel btnPanel = new JPanel(); btnPanel.add(btnAdd); btnPanel.add(btnUpdate); btnPanel.add(btnDelete); btnPanel.add(btnRefresh); btnPanel.add(btnClear); form.add(btnPanel); add(form, BorderLayout.SOUTH); btnAdd.addActionListener(e -> addClass()); btnUpdate.addActionListener(e -> updateClass()); btnDelete.addActionListener(e -> deleteClass()); btnRefresh.addActionListener(e -> refreshTable()); btnClear.addActionListener(e -> clearForm()); table.getSelectionModel().addListSelectionListener(evt -> { if (!evt.getValueIsAdjusting()) fillForm(); }); } private void loadClasses() { try { List<SchoolClass> classes = classDao.getAllClasses(); for (SchoolClass c : classes) { model.addRow(new Object[]{ c.getId(), c.getClassName(), c.getGrade(), c.getHomeroomTeacherId(), c.getEnrollmentYear(), c.getMajor(), c.getDepartment(), c.getCurrentStudentCount(), c.getMaxCapacity(), c.getCreatedAt(), c.isActive() ? "正常" : "停用" }); } } catch (Exception e) { JOptionPane.showMessageDialog(this, "加载失败:" + e.getMessage()); } } private void addClass() { try { SchoolClass c = new SchoolClass(); c.setId(Integer.parseInt(txtId.getText())); c.setClassName(txtClassName.getText().trim()); c.setGrade(txtGrade.getText().trim()); c.setHomeroomTeacherId(Integer.parseInt(txtTeacherId.getText())); c.setEnrollmentYear(Integer.parseInt(txtYear.getText())); c.setMajor(txtMajor.getText().trim()); c.setDepartment(txtDept.getText().trim()); c.setCurrentStudentCount(Integer.parseInt(txtCount.getText())); c.setMaxCapacity(Integer.parseInt(txtCap.getText())); c.setCreatedAt(Date.valueOf(txtCreatedAt.getText())); c.setActive(chkActive.isSelected()); classDao.insertClass(c); model.addRow(new Object[]{ c.getId(), c.getClassName(), c.getGrade(), c.getHomeroomTeacherId(), c.getEnrollmentYear(), c.getMajor(), c.getDepartment(), c.getCurrentStudentCount(), c.getMaxCapacity(), c.getCreatedAt(), c.isActive() ? "正常" : "停用" }); JOptionPane.showMessageDialog(this, "✅ 添加成功!"); clearForm(); } catch (Exception e) { JOptionPane.showMessageDialog(this, "❌ 添加失败:" + e.getMessage()); } } private void updateClass() { int row = table.getSelectedRow(); if (row < 0) { JOptionPane.showMessageDialog(this, "请选择要修改的班级!"); return; } try { SchoolClass c = new SchoolClass(); c.setId(Integer.parseInt(txtId.getText())); c.setClassName(txtClassName.getText().trim()); c.setGrade(txtGrade.getText().trim()); c.setHomeroomTeacherId(Integer.parseInt(txtTeacherId.getText())); c.setEnrollmentYear(Integer.parseInt(txtYear.getText())); c.setMajor(txtMajor.getText().trim()); c.setDepartment(txtDept.getText().trim()); c.setCurrentStudentCount(Integer.parseInt(txtCount.getText())); c.setMaxCapacity(Integer.parseInt(txtCap.getText())); c.setCreatedAt(Date.valueOf(txtCreatedAt.getText())); c.setActive(chkActive.isSelected()); classDao.updateClass(c); model.setValueAt(c.getClassName(), row, 1); model.setValueAt(c.getGrade(), row, 2); model.setValueAt(c.getHomeroomTeacherId(), row, 3); model.setValueAt(c.getEnrollmentYear(), row, 4); model.setValueAt(c.getMajor(), row, 5); model.setValueAt(c.getDepartment(), row, 6); model.setValueAt(c.getCurrentStudentCount(), row, 7); model.setValueAt(c.getMaxCapacity(), row, 8); model.setValueAt(c.getCreatedAt(), row, 9); model.setValueAt(c.isActive() ? "正常" : "停用", row, 10); JOptionPane.showMessageDialog(this, "✅ 修改成功!"); } catch (Exception e) { JOptionPane.showMessageDialog(this, "❌ 修改失败:" + e.getMessage()); } } private void deleteClass() { int row = table.getSelectedRow(); if (row < 0) return; int id = (int) model.getValueAt(row, 0); if (JOptionPane.showConfirmDialog(this, "确认删除 ID=" + id + " 的班级?") == JOptionPane.YES_OPTION) { try { classDao.deleteClass(id); model.removeRow(row); JOptionPane.showMessageDialog(this, "✅ 删除成功!"); } catch (Exception e) { JOptionPane.showMessageDialog(this, "❌ 删除失败:" + e.getMessage()); } } } private void refreshTable() { model.setRowCount(0); loadClasses(); } private void fillForm() { int row = table.getSelectedRow(); if (row < 0) return; txtId.setText(model.getValueAt(row, 0).toString()); txtClassName.setText(model.getValueAt(row, 1).toString()); txtGrade.setText(model.getValueAt(row, 2).toString()); txtTeacherId.setText(model.getValueAt(row, 3).toString()); txtYear.setText(model.getValueAt(row, 4).toString()); txtMajor.setText(model.getValueAt(row, 5).toString()); txtDept.setText(model.getValueAt(row, 6).toString()); txtCount.setText(model.getValueAt(row, 7).toString()); txtCap.setText(model.getValueAt(row, 8).toString()); txtCreatedAt.setText(model.getValueAt(row, 9).toString()); chkActive.setSelected("正常".equals(model.getValueAt(row, 10))); } private void clearForm() { txtId.setText(""); txtClassName.setText(""); txtGrade.setText(""); txtTeacherId.setText(""); txtYear.setText(""); txtMajor.setText(""); txtDept.setText(""); txtCount.setText(""); txtCap.setText(""); txtCreatedAt.setText(""); chkActive.setSelected(true); } } ``` --- # ✅ 5. 选课管理面板:`EnrollmentManagementPanel.java` ```java // gui/EnrollmentManagementPanel.java package gui; import dao.EnrollmentDao; import dao.impl.EnrollmentDaoImpl; import entity.Enrollment; import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.util.Date; import java.sql.Timestamp; public class EnrollmentManagementPanel extends JPanel { private final EnrollmentDao enrollmentDao = new EnrollmentDaoImpl(); private final DefaultTableModel model = new DefaultTableModel( new String[]{"学生ID", "课程代码", "选课时间", "成绩", "等级", "状态", "是否通过", "补考", "备注"}, 0); private final JTable table = new JTable(model); private final JTextField txtStuId = new JTextField(8); private final JTextField txtCourseCode = new JTextField(10); private final JTextField txtTime = new JTextField(15); // 格式:YYYY-MM-DD HH:MM:SS private final JTextField txtGrade = new JTextField(6); private final JTextField txtLevel = new JTextField(6); private final JTextField txtStatus = new JTextField(10); private final JCheckBox chkPassed = new JCheckBox("通过"); private final JCheckBox chkMakeUp = new JCheckBox("补考"); private final JTextField txtComment = new JTextField(15); public EnrollmentManagementPanel() { setLayout(new BorderLayout()); loadEnrollments(); add(new JScrollPane(table), BorderLayout.CENTER); JPanel form = new JPanel(new GridLayout(3, 5, 10, 10)); form.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); form.add(new JLabel("学生ID:", SwingConstants.RIGHT)); form.add(txtStuId); form.add(new JLabel("课程代码:", SwingConstants.RIGHT)); form.add(txtCourseCode); form.add(new JLabel("选课时间:", SwingConstants.RIGHT)); form.add(txtTime); form.add(new JLabel("成绩:", SwingConstants.RIGHT)); form.add(txtGrade); form.add(new JLabel("等级:", SwingConstants.RIGHT)); form.add(txtLevel); form.add(new JLabel("状态:", SwingConstants.RIGHT)); form.add(txtStatus); form.add(chkPassed); form.add(chkMakeUp); form.add(new JLabel("备注:", SwingConstants.RIGHT)); form.add(txtComment); JButton btnAdd = new JButton("添加"); JButton btnUpdate = new JButton("修改"); JButton btnDelete = new JButton("删除"); JButton btnRefresh = new JButton("刷新"); JButton btnClear = new JButton("清空"); JPanel btnPanel = new JPanel(); btnPanel.add(btnAdd); btnPanel.add(btnUpdate); btnPanel.add(btnDelete); btnPanel.add(btnRefresh); btnPanel.add(btnClear); form.add(btnPanel); add(form, BorderLayout.SOUTH); btnAdd.addActionListener(e -> addEnrollment()); btnUpdate.addActionListener(e -> updateEnrollment()); btnDelete.addActionListener(e -> deleteEnrollment()); btnRefresh.addActionListener(e -> refreshTable()); btnClear.addActionListener(e -> clearForm()); table.getSelectionModel().addListSelectionListener(evt -> { if (!evt.getValueIsAdjusting()) fillForm(); }); } private void loadEnrollments() { try { List<Enrollment> list = enrollmentDao.getAllEnrollments(); for (Enrollment e : list) { model.addRow(new Object[]{ e.getStudentId(), e.getCourseCode(), e.getEnrollmentTime(), e.getGrade(), e.getGradeLevel(), e.getStatus(), e.isPassed() ? "是" : "否", e.isMakeUpExam() ? "是" : "否", e.getComment() }); } } catch (Exception ex) { JOptionPane.showMessageDialog(this, "加载失败:" + ex.getMessage()); } } private void addEnrollment() { try { Enrollment e = new Enrollment(); e.setStudentId(Integer.parseInt(txtStuId.getText())); e.setCourseCode(txtCourseCode.getText().trim()); e.setEnrollmentTime(Timestamp.valueOf(txtTime.getText())); e.setGrade(txtGrade.getText().isEmpty() ? null : Double.parseDouble(txtGrade.getText())); e.setGradeLevel(txtLevel.getText().trim()); e.setStatus(txtStatus.getText().trim()); e.setPassed(chkPassed.isSelected()); e.setMakeUpExam(chkMakeUp.isSelected()); e.setComment(txtComment.getText().trim()); enrollmentDao.insertEnrollment(e); model.addRow(new Object[]{ e.getStudentId(), e.getCourseCode(), e.getEnrollmentTime(), e.getGrade(), e.getGradeLevel(), e.getStatus(), e.isPassed() ? "是" : "否", e.isMakeUpExam() ? "是" : "否", e.getComment() }); JOptionPane.showMessageDialog(this, "✅ 添加成功!"); clearForm(); } catch (Exception ex) { JOptionPane.showMessageDialog(this, "❌ 添加失败:" + ex.getMessage()); } } private void updateEnrollment() { int row = table.getSelectedRow(); if (row < 0) { JOptionPane.showMessageDialog(this, "请选择一条记录!"); return; } try { Enrollment e = new Enrollment(); e.setStudentId(Integer.parseInt(txtStuId.getText())); e.setCourseCode(txtCourseCode.getText().trim()); e.setEnrollmentTime(Timestamp.valueOf(txtTime.getText())); e.setGrade(txtGrade.getText().isEmpty() ? null : Double.parseDouble(txtGrade.getText())); e.setGradeLevel(txtLevel.getText().trim()); e.setStatus(txtStatus.getText().trim()); e.setPassed(chkPassed.isSelected()); e.setMakeUpExam(chkMakeUp.isSelected()); e.setComment(txtComment.getText().trim()); enrollmentDao.updateEnrollment(e); model.setValueAt(e.getGrade(), row, 3); model.setValueAt(e.getGradeLevel(), row, 4); model.setValueAt(e.getStatus(), row, 5); model.setValueAt(e.isPassed() ? "是" : "否", row, 6); model.setValueAt(e.isMakeUpExam() ? "是" : "否", row, 7); model.setValueAt(e.getComment(), row, 8); JOptionPane.showMessageDialog(this, "✅ 修改成功!"); } catch (Exception ex) { JOptionPane.showMessageDialog(this, "❌ 修改失败:" + ex.getMessage()); } } private void deleteEnrollment() { int row = table.getSelectedRow(); if (row < 0) return; int sid = (int) model.getValueAt(row, 0); String code = (String) model.getValueAt(row, 1); if (JOptionPane.showConfirmDialog(this, "确认删除 学生" + sid + " 的选课 " + code + "?") == JOptionPane.YES_OPTION) { try { enrollmentDao.deleteEnrollment(sid, code); model.removeRow(row); JOptionPane.showMessageDialog(this, "✅ 删除成功!"); } catch (Exception ex) { JOptionPane.showMessageDialog(this, "❌ 删除失败:" + ex.getMessage()); } } } private void refreshTable() { model.setRowCount(0); loadEnrollments(); } private void fillForm() { int row = table.getSelectedRow(); if (row < 0) return; txtStuId.setText(model.getValueAt(row, 0).toString()); txtCourseCode.setText(model.getValueAt(row, 1).toString()); txtTime.setText(model.getValueAt(row, 2).toString()); txtGrade.setText(model.getValueAt(row, 3) == null ? "" : model.getValueAt(row, 3).toString()); txtLevel.setText(model.getValueAt(row, 4).toString()); txtStatus.setText(model.getValueAt(row, 5).toString()); chkPassed.setSelected("是".equals(model.getValueAt(row, 6))); chkMakeUp.setSelected("是".equals(model.getValueAt(row, 7))); txtComment.setText(model.getValueAt(row, 8).toString()); } private void clearForm() { txtStuId.setText(""); txtCourseCode.setText(""); txtTime.setText(""); txtGrade.setText(""); txtLevel.setText(""); txtStatus.setText(""); chkPassed.setSelected(false); chkMakeUp.setSelected(false); txtComment.setText(""); } } ``` --- ## ✅ 总结 | 面板 | 功能 | |------|------| | `StudentManagementPanel` | 学生信息增删改查 | | `TeacherManagementPanel` | 教师信息维护 | | `CourseManagementPanel` | 课程设置与管理 | | `ClassManagementPanel` | 班级结构管理 | | `EnrollmentManagementPanel` | 选课与成绩记录 | 所有面板均已接入真实 DAO 层,可直接运行并与 MySQL 数据库交互。 ---
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值