用Java Swing + MySQL 8.0 手把手教你做一个数据库课程设计GUI(附完整源码)
Java Swing与MySQL 8.0实战:从零构建数据库课程设计GUI应用
在计算机专业的课程设计中,数据库应用开发一直是重点实践环节。本文将带你使用Java Swing和MySQL 8.0,一步步构建一个功能完整的数据库GUI应用。不同于简单的实验记录,我们将从工程化角度出发,涵盖环境配置、界面设计、数据库交互等全流程,并提供可直接运行的完整源码。
1. 开发环境准备与MySQL配置
构建Java数据库应用的第一步是搭建稳定的开发环境。我们选择IntelliJ IDEA作为开发工具,MySQL 8.0作为数据库服务器,这是目前最主流的组合方案。
MySQL 8.0安装关键步骤:
- 从官网下载MySQL Community Server 8.0.25+版本
- 配置my.ini初始化文件,设置字符集为utf8mb4
- 以管理员身份运行CMD,执行初始化命令:
mysqld --initialize --console - 安装MySQL服务并启动:
mysqld --install net start mysql
注意:MySQL 8.0默认使用caching_sha2_password认证插件,可能导致旧版本连接工具兼容性问题。如需使用传统验证方式,可在my.ini中添加:
default_authentication_plugin=mysql_native_password
Java连接MySQL时,常见的时区问题可通过在JDBC URL中添加参数解决:
String url = "jdbc:mysql://localhost:3306/student_db?serverTimezone=UTC";
2. 项目结构与基础框架搭建
我们采用Maven管理项目依赖,pom.xml需包含以下关键依赖:
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
</dependencies>
推荐的项目结构如下:
src/
├── main/
│ ├── java/
│ │ ├── controller/ # 控制器层
│ │ ├── dao/ # 数据访问层
│ │ ├── model/ # 数据模型
│ │ ├── util/ # 工具类
│ │ └── view/ # 视图层
│ └── resources/
└── test/ # 测试代码
数据库连接工具类示例:
public class DBUtil {
private static final String URL = "jdbc:mysql://localhost:3306/student_db";
private static final String USER = "root";
private static final String PASSWORD = "123456";
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();
if (stmt != null) stmt.close();
if (conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
3. Swing界面设计与布局技巧
Java Swing提供了丰富的GUI组件,合理使用布局管理器是关键。我们采用分层设计思路:
主界面框架设计:
public class MainFrame extends JFrame {
private JTabbedPane tabbedPane;
public MainFrame() {
setTitle("学生课程管理系统");
setSize(800, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 初始化组件
initComponents();
// 设置布局
setLayout(new BorderLayout());
add(tabbedPane, BorderLayout.CENTER);
}
private void initComponents() {
tabbedPane = new JTabbedPane();
tabbedPane.addTab("学生管理", new StudentPanel());
tabbedPane.addTab("课程管理", new CoursePanel());
tabbedPane.addTab("成绩管理", new ScorePanel());
}
}
使用JFormDesigner提升开发效率:
- 在IDEA中安装JFormDesigner插件
- 创建新Form时选择JFrame或JPanel
- 通过拖拽方式设计界面,自动生成代码
- 关键设置:
- 将布局设置为null(绝对定位)
- 使用setBounds(x, y, width, height)精确定位组件
- 为按钮等组件添加事件监听器
表格数据显示最佳实践:
// 创建带滚动条的表格
String[] columnNames = {"学号", "姓名", "性别", "年龄", "班级"};
DefaultTableModel model = new DefaultTableModel(columnNames, 0);
JTable table = new JTable(model);
JScrollPane scrollPane = new JScrollPane(table);
// 从数据库加载数据
public void loadStudentData() {
try (Connection conn = DBUtil.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM student")) {
model.setRowCount(0); // 清空现有数据
while (rs.next()) {
Object[] row = {
rs.getString("sno"),
rs.getString("sname"),
rs.getString("ssex"),
rs.getInt("sage"),
rs.getString("sclass")
};
model.addRow(row);
}
} catch (SQLException e) {
JOptionPane.showMessageDialog(this, "加载数据失败: " + e.getMessage());
}
}
4. 数据库交互与SQL动态生成
在数据库应用中,动态SQL生成是核心技能。我们对比三种常用方式:
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Statement | 简单直接 | SQL注入风险 | 静态SQL |
| PreparedStatement | 防注入,高性能 | 代码稍复杂 | 参数化查询 |
| JPA/Hibernate | 面向对象,开发快 | 学习曲线陡 | 大型项目 |
PreparedStatement使用示例:
public boolean addStudent(Student student) {
String sql = "INSERT INTO student(sno, sname, ssex, sage, sclass) VALUES(?,?,?,?,?)";
try (Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, student.getSno());
pstmt.setString(2, student.getSname());
pstmt.setString(3, student.getSsex());
pstmt.setInt(4, student.getSage());
pstmt.setString(5, student.getSclass());
return pstmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
动态查询构建技巧:
public List<Student> searchStudents(Student condition) {
List<Student> students = new ArrayList<>();
StringBuilder sql = new StringBuilder("SELECT * FROM student WHERE 1=1");
List<Object> params = new ArrayList<>();
if (condition.getSno() != null) {
sql.append(" AND sno LIKE ?");
params.add("%" + condition.getSno() + "%");
}
if (condition.getSname() != null) {
sql.append(" AND sname LIKE ?");
params.add("%" + condition.getSname() + "%");
}
// 其他条件...
try (Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql.toString())) {
for (int i = 0; i < params.size(); i++) {
pstmt.setObject(i + 1, params.get(i));
}
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
Student student = new Student();
student.setSno(rs.getString("sno"));
student.setSname(rs.getString("sname"));
// 设置其他属性...
students.add(student);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return students;
}
5. 高级功能实现与性能优化
分页查询实现:
public PageResult<Student> getStudentsByPage(int pageNum, int pageSize) {
PageResult<Student> result = new PageResult<>();
String countSql = "SELECT COUNT(*) FROM student";
String dataSql = "SELECT * FROM student LIMIT ?,?";
try (Connection conn = DBUtil.getConnection()) {
// 查询总记录数
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(countSql)) {
if (rs.next()) {
result.setTotal(rs.getInt(1));
}
}
// 查询当前页数据
try (PreparedStatement pstmt = conn.prepareStatement(dataSql)) {
pstmt.setInt(1, (pageNum - 1) * pageSize);
pstmt.setInt(2, pageSize);
try (ResultSet rs = pstmt.executeQuery()) {
List<Student> list = new ArrayList<>();
while (rs.next()) {
Student student = new Student();
// 设置属性...
list.add(student);
}
result.setData(list);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
事务处理示例:
public boolean updateStudentScore(String sno, String cno, int score) {
Connection conn = null;
try {
conn = DBUtil.getConnection();
conn.setAutoCommit(false); // 开启事务
// 检查学生是否存在
String checkStudent = "SELECT 1 FROM student WHERE sno = ?";
try (PreparedStatement pstmt = conn.prepareStatement(checkStudent)) {
pstmt.setString(1, sno);
try (ResultSet rs = pstmt.executeQuery()) {
if (!rs.next()) {
throw new SQLException("学生不存在");
}
}
}
// 更新成绩
String updateSql = "UPDATE sc SET score = ? WHERE sno = ? AND cno = ?";
try (PreparedStatement pstmt = conn.prepareStatement(updateSql)) {
pstmt.setInt(1, score);
pstmt.setString(2, sno);
pstmt.setString(3, cno);
int affected = pstmt.executeUpdate();
if (affected == 0) {
throw new SQLException("成绩记录不存在");
}
}
conn.commit(); // 提交事务
return true;
} catch (SQLException e) {
if (conn != null) {
try {
conn.rollback(); // 回滚事务
} catch (SQLException ex) {
ex.printStackTrace();
}
}
e.printStackTrace();
return false;
} finally {
DBUtil.close(conn, null, null);
}
}
性能优化建议:
- 使用连接池(如HikariCP)管理数据库连接
- 批量操作使用addBatch()和executeBatch()
- 合理使用索引提高查询效率
- 对频繁访问的数据考虑使用缓存
6. 项目打包与部署
完成开发后,我们需要将项目打包为可执行的JAR文件:
- 在pom.xml中添加maven-assembly-plugin配置
- 执行mvn package assembly:single命令
- 生成的包含所有依赖的JAR文件可在命令行运行:
java -jar student-management.jar
对于更专业的部署,可以考虑:
- 使用Launch4j将JAR转换为EXE文件
- 使用Inno Setup等工具创建Windows安装程序
- 使用jpackage(JDK14+)生成原生安装包
在实际教学中发现,学生最容易出错的地方是数据库连接资源的释放。务必确保Connection、Statement和ResultSet在使用后正确关闭,推荐使用try-with-resources语法自动管理资源。
更多推荐
所有评论(0)