Java+MySQL图书馆管理系统:数据库设计、JDBC与事务实战解析
简介面向Java期末大作业和课程设计场景这套图书馆信息管理系统基于Java和MySQL实现支持书名、作者、日期、出版社等多条件检索并包含登录、借阅、归还等核心流程界面完整、代码清晰适合需要快速跑通项目并完成期末文档的在校学生。压缩包共86个文件整体约2.22MB涵盖11个Java源码、47个class编译文件、1份SQL数据库脚本、1份docx作业文档以及多张png/jpg界面截图和工程配置说明文件项目目录区分src源码、bin编译输出和资源文件SQL脚本包含建库建表语句及测试数据便于对照源码理解模块设计也可直接导入运行验证效果。配套演示视频与安装教程视频从Java环境安装讲到MySQL数据库配置步骤详细新手按视频操作即可在本地成功跑起来。目前已有10173人学习下载是图书馆信息管理系统期末项目、课程设计或JavaMySQL入门练手的实用参考。1. 图书馆信息管理系统作为 JavaMySQL 期末大作业它到底在考什么期末大作业选「图书馆信息管理系统」这个题目的学生远比选「学生管理系统」「超市收银系统」的人多原因很实在业务模型足够典型书、读者、借阅、归还、逾期每一块都能对应到数据库表关系和 Java 面向对象设计老师一眼能看出你有没有真做同时工作量又卡得刚好一个人两周能写完不会像电商系统那样收不住尾。这套题实际检验的是三件事MySQL 表结构设计是否合理、JDBC 操作是否熟练、Swing 或 JSP 前端和数据库之间能不能顺畅对接。标题里的「完整版项目代码文档演示视频安装教程视频」对应的是你交付时拿得出手的五个东西而不是只交一个能跑起来的压缩包。本文会按我自己做这类项目的顺序拆先定数据模型再写 JDBC 和数据访问层接着把项目在本机跑起来然后把最容易翻车的地方单独拎出来讲最后说演示视频和答辩文档怎么准备。每一段你都能直接照抄代码或配置我会把参数含义和踩过的坑都标出来。2. 把图书馆业务拆成 5 张表数据模型设计是拿分的关键2.1 为什么是这 5 张表从借阅流程反推表结构很多人的第一个错误是一上来就写代码表结构边写边改最后项目能跑但一问三张表之间是什么关系就答不上来。正确做法是先走一遍业务读者来借书系统要记录谁借了哪本书、什么时候借的、什么时候该还管理员要看到书库里有哪些书、库存剩多少。这背后最少需要 5 张表图书表book、读者表reader、借阅记录表borrow、分类表category、管理员表admin。借阅记录表是整个系统的核心它通过 book_id 和 reader_id 关联另外两张表。图书表里单独放一个 category_id是为了避免在 book 表里直接存分类名字符串——存名字会导致数据冗余而且改分类名时要 UPDATE 多条记录这是数据库设计基础题里最常考的点。管理员表独立出来是因为管理员登录和读者登录权限不同混在一张表里会让权限判断变麻烦。我一般会在设计文档里画三句话解释这三张核心表的关系「一本书属于一个分类」「一个读者可以借多本书」「一条借阅记录同时关联一本书和一个读者」。这不只是写文档用答辩时老师第一个问题往往就是「为什么 borrow 表要单独建」。2.2 建表 SQL字段类型、默认值、字符集一次到位直接给一份能用的建表 SQL我按企业项目的习惯加了注释。注意字符集统一用 utf8mb4不要用 utf8因为 utf8 在 MySQL 里存不了生僻字和部分特殊符号比如借阅备注里的 emojiutf8mb4 才是真正的四字节 UTF-8。-- 分类表 CREATE TABLE category ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 分类ID, name VARCHAR(50) NOT NULL UNIQUE COMMENT 分类名称 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 图书表 CREATE TABLE book ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 图书ID, book_name VARCHAR(100) NOT NULL COMMENT 书名, author VARCHAR(50) DEFAULT COMMENT 作者, publisher VARCHAR(100) DEFAULT COMMENT 出版社, category_id INT NOT NULL COMMENT 分类ID逻辑外键, stock INT NOT NULL DEFAULT 1 COMMENT 库存数量, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 入库时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 读者表 CREATE TABLE reader ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 读者ID, reader_no VARCHAR(20) NOT NULL UNIQUE COMMENT 借书证号, name VARCHAR(50) NOT NULL COMMENT 姓名, phone VARCHAR(20) DEFAULT COMMENT 手机号, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 借阅记录表 CREATE TABLE borrow ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 记录ID, book_id INT NOT NULL COMMENT 图书ID, reader_id INT NOT NULL COMMENT 读者ID, borrow_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 借书时间, due_time DATETIME COMMENT 应还时间, return_time DATETIME DEFAULT NULL COMMENT 实际归还时间, status TINYINT NOT NULL DEFAULT 0 COMMENT 0借出中 1已归还 2逾期未还, KEY idx_book_id (book_id), KEY idx_reader_id (reader_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里有几个关键点图书表的 category_id 我写的是逻辑外键而不是物理外键也就是说建表时不加 FOREIGN KEY 约束。期末项目里加物理外键会导致插入数据必须严格按顺序来删除分类时还要处理约束冲突很多学生在答辩演示时当场报错就是这个原因。逻辑外键靠程序保证一致性对课程设计来说完全够用我会在文档里主动说明这个选择——这反而是加分项说明你想过外键的利弊。借阅记录的 status 字段用 TINYINT 而不是 VARCHAR存 0/1/2 三个数字查询和统计都更快。due_time应还时间和 return_time实际归还时间必须分开不能只存一个否则「逾期判断」和「归还登记」会打架。逾期判断的 SQL 在答辩时很常被问到我后面写给你。2.3 索引和引擎为什么 InnoDB 是唯一选择上面每张表我都指定了 ENGINEInnoDB这不是随手写的。期末项目里最容易出现的两个问题一是有人用默认的 MyISAM 引擎二是建表时不加任何索引。MyISAM 不支持事务如果你的项目里做了「借书时要同时更新库存和插入借阅记录」这种两步操作中间任何一步失败数据就脏了。InnoDB 支持事务配合后面的 JDBC 代码可以把两步操作放在同一个事务里要么都成功要么都失败。索引方面borrow 表上我建了 idx_book_id 和 idx_reader_id 两个普通索引。原因是查询「某个读者借了哪些书」和「某本书被谁借走了」是最常见的两个查询如果不在外键列上建索引MySQL 每次都要全表扫描。这个细节你写在文档的「设计说明」里比在代码里堆功能更能体现水平。另外提醒一个默认值问题reader 表的 create_time 用了 DEFAULT CURRENT_TIMESTAMP但 borrow 表的 return_time 故意没设默认值而是用 DEFAULT NULL。原因是借出时 return_time 本来就还不存在让它为空是业务语义的正确表达。如果你给所有时间字段都设 CURRENT_TIMESTAMP归还时间会被自动填成借书时间这是一个非常隐蔽的逻辑错误。3. 用 JDBC 写数据访问层连接池、预处理语句和事务三个必会点3.1 最稳妥的技术选型Swing JDBC MySQL不要碰框架期末大作业的技术栈选择有个现实原则能用框架但别用你没把握在答辩时讲清楚的框架。JSPServlet 是很多学校的标准要求Swing 是单机版课程设计最常见的桌面方案。我不建议在期末项目里引入 MyBatis 或 Spring Boot不是这些技术不好而是你答辩时被问「MyBatis 的一级缓存和二级缓存有什么区别」的概率远大于被问「JDBC 的 PreparedStatement 和 Statement 有什么区别」的概率后者你能稳答前者容易翻车。这套项目的最佳结构是三层的简化版界面层Swing 或 JSP→ 数据访问层DAO→ 数据库MySQL。界面层不写 SQLDAO 里不写按钮事件各层职责清楚代码量不大但结构规整。我见过很多学生把 SQL 直接写在按钮的监听器里虽然能跑但老师看一眼就说这是「面向过程的 Java」分数直接掉一档。3.2 第一个代码块使用连接池而不是 DriverManager学校教材里教的是 Class.forName DriverManager.getConnection但真实的 Java 项目没人这么写。原因很简单每次连接都经历 TCP 握手、认证、断开高并发下性能极差。用连接池可以让程序启动时预创建一批连接用完归还而不是关闭。期末项目规模小引入 Druid 连接池并不会增加多少代码量却是一个能在文档里写一整页的亮点。以下是基于 Druid 的连接池工具类Druid 是阿里巴巴开源的配置简单你不需要深入它的源码package util; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; public class DBUtil { private static DataSource dataSource; // 静态代码块类加载时执行一次初始化连接池 static { try { Properties props new Properties(); // 配置文件放在 src 目录下名为 db.properties InputStream in DBUtil.class.getClassLoader().getResourceAsStream(db.properties); props.load(in); dataSource DruidDataSourceFactory.createDataSource(props); } catch (Exception e) { e.printStackTrace(); } } // 从连接池取连接 public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }对应的 db.properties 配置文件放在 src 根目录driverClassNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/library?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8 usernameroot password你的数据库密码 initialSize5 maxActive10 maxWait3000注意三个参数。driverClassName 在 MySQL 8.x 下必须是 com.mysql.cj.jdbc.Driver旧版的 com.mysql.jdbc.Driver 虽然也能用但会在日志里打警告属于「能跑但不体面」。url 里的 serverTimezoneAsia/Shanghai 必须加MySQL 8.x 不指定时区会报 CST 时区识别错误的异常characterEncodingutf8 配合 utf8mb4 字符集是为了让中文不乱码。initialSize 和 maxActive 分别是初始连接数和最大连接数期末项目 5 和 10 就够别调大连接数太大会让 MySQL 吃内存。3.3 第二个代码块PreparedStatement 为什么必须用数据访问层写 SQL 时只能用 PreparedStatement不用 Statement。核心原因是 SQL 注入如果你用字符串拼接把读者输入直接拼进 SQL比如「DELETE FROM reader WHERE id 」加上输入框内容对方输入「1 OR 11」就能删掉全部读者。PreparedStatement 用 ? 占位符传参参数和 SQL 语句结构分离数据库驱动会自动处理转义。下面是图书管理的 DAO 方法演示查询和插入两种操作package dao; import util.DBUtil; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class BookDao { // 查询所有图书 public ListBook findAll() { ListBook list new ArrayList(); String sql SELECT id, book_name, author, publisher, category_id, stock FROM book; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { while (rs.next()) { Book book new Book(); book.setId(rs.getInt(id)); book.setBookName(rs.getString(book_name)); book.setAuthor(rs.getString(author)); book.setPublisher(rs.getString(publisher)); book.setCategoryId(rs.getInt(category_id)); book.setStock(rs.getInt(stock)); list.add(book); } } catch (SQLException e) { e.printStackTrace(); } return list; } // 新增图书返回受影响行数 public int insert(Book book) { String sql INSERT INTO book(book_name, author, publisher, category_id, stock) VALUES(?, ?, ?, ?, ?); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, book.getBookName()); ps.setString(2, book.getAuthor()); ps.setString(3, book.getPublisher()); ps.setInt(4, book.getCategoryId()); ps.setInt(5, book.getStock()); return ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); return 0; } } }这段代码里用了 Java 7 的 try-with-resources 语法Connection、PreparedStatement、ResultSet 会自动关闭。注意 ResultSet 也要手动关很多学生只关 Connection导致数据库连接被连接池回收后关联的结果集没有释放运行久了连接池的连接全被占满。setString 和 setInt 是按序号对应 ? 的位置第一个 ? 的序号是 1不是 0这是新手最容易写错的地方。如果你发现插入的数据错位或报「Parameter index out of range」先数一遍问号个数和 set 方法的序号。3.4 事务处理借书操作必须写成原子操作借书这个动作在数据库层面包含两步更新图书库存减一插入一条借阅记录。两步必须在一个事务里否则可能出现库存减了但借阅记录没插上或者反过来的情况。下面这段代码是事务的标准写法期末项目的加分点就在这里。package service; import util.DBUtil; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class BorrowService { public boolean borrowBook(int bookId, int readerId) { String updateStock UPDATE book SET stock stock - 1 WHERE id ? AND stock 0; String insertBorrow INSERT INTO borrow(book_id, reader_id, due_time, status) VALUES(?, ?, DATE_ADD(NOW(), INTERVAL 30 DAY), 0); try (Connection conn DBUtil.getConnection()) { // 关键关闭自动提交改为手动控制事务 conn.setAutoCommit(false); try (PreparedStatement ps1 conn.prepareStatement(updateStock)) { ps1.setInt(1, bookId); int rows ps1.executeUpdate(); if (rows 0) { // 库存不足回滚 conn.rollback(); return false; } } try (PreparedStatement ps2 conn.prepareStatement(insertBorrow)) { ps2.setInt(1, bookId); ps2.setInt(2, readerId); ps2.executeUpdate(); } // 两步都成功才提交 conn.commit(); return true; } catch (SQLException e) { e.printStackTrace(); // 异常时回滚 if (conn ! null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } return false; } } }这段代码有两个细节值得在文档里写。第一UPDATE 语句里带了「AND stock 0」条件如果库存已经是 0执行影响行数为 0说明借不了直接回滚这是用乐观锁思路避免超借。第二DATE_ADD(NOW(), INTERVAL 30 DAY) 把应还时间设为借书后 30 天SQL 函数写在语句里而不是在 Java 代码里算好再传参能让时间计算依托数据库服务器时间避免客户端和服务器时间不一致。事务里最容易忽略的问题是把 setAutoCommit(false) 写在 try-with-resources 外面还是里面必须写在拿到 Connection 之后、执行第一条 SQL 之前。如果你在连接池获取连接后没有关自动提交那么 executeUpdate 每执行一次就自动持久化事务就失去意义了。4. 在本机跑通这个项目从 JDK 到 MySQL 到演示数据的全流程4.1 环境准备JDK、MySQL、连接工具三件套的版本匹配跑通这个项目首先要解决环境问题我见过太多项目本身没问题、卡在环境装不上。先说版本匹配JDK 建议装 8 或 11对应 javax 开头的 Swing 包太新的 JDK 比如 17 或 21 在部分 Windows 老机器上会有显示缩放问题MySQL 装 5.7 或 8.0 都行但 8.0 的驱动类名和认证方式跟 5.7 不同代码里按 8.0 写就统一用 8.0。MySQL 安装时有两个关键选项字符集选 utf8mb4认证插件选「Use Legacy Authentication」或者安装后在命令行执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 密码;。为什么强调这个因为 MySQL 8.0 默认的 caching_sha2_password 插件在某些旧版 JDBC 驱动mysql-connector-java 5.x下会报「Public Key Retrieval is not allowed」错误很多人卡在这一步。如果你用的是 mysql-connector-j 8.x 驱动可以直接在 JDBC url 里加 allowPublicKeyRetrievaltrue 解决。连接工具方面Navicat 和 MySQL Workbench 二选一。MySQL Workbench 免费且不存在激活问题适合学生项目Navicat 在热搜词里常被搜到但它是收费软件不要为此冒险Workbench 完全够用。我一般会用命令行客户端做验证因为答辩时老师可能没有图形界面工具命令行操作反而更能说明你真的懂。4.2 导入项目和数据库手把手操作步骤拿到项目压缩包后按以下步骤执行。先建数据库再建表再导入测试数据顺序不能反。如果是 Windows 系统注意 SQL 脚本里如果有中文注释要确认文件编码是 UTF-8否则用命令行 source 导入时注释会乱码。# 第一步登录 MySQL密码替换成你自己的 mysql -u root -p # 第二步创建数据库并指定字符集 CREATE DATABASE library DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 第三步切换数据库然后用 source 执行建表脚本假设脚本在 D 盘根目录 USE library; source D:/library_db.sql; # 第四步查看表是否创建成功 SHOW TABLES;执行完 SHOW TABLES 应该看到 category、book、reader、borrow、admin 五张表。如果少了表检查脚本里有没有 DROP TABLE IF EXISTS 语句或者有没有因为前面建表出错导致后续语句没执行。source 命令在执行时如果某条 SQL 报错会把错误显示在终端里但后面的 SQL 还会继续跑所以不要只看最后有没有报错就完事要回头翻日志。导入测试数据我建议用 SQL 脚本而不是在界面里一条条录既省时间又能保证数据格式正确。写几条有代表性的数据图书至少 10 本覆盖 3 个分类读者 5 个借阅记录里要有「已归还」「借出中」「逾期未还」三种状态。这三种状态能让你的查询功能演示变得非常自然特别是逾期列表一打开就有数据可以展示。4.3 修改项目里的数据库连接配置并启动项目代码里 DBUtil 从 db.properties 读连接信息改成你自己的 MySQL 端口、用户名、密码即可。端口默认 3306如果你安装时改过端口这里要同步改。下面是我建议的启动顺序能帮你区分是配置问题还是代码问题。# 1. 先用命令行确认 MySQL 服务正在运行Windows 下 net start | findstr mysql # 2. 用命令行确认能连上数据库这一步能排除 Navicat 连接正常但代码连不上的情况 mysql -u root -p -h 127.0.0.1 -P 3306 # 3. 在 IDEA 里刷新 Maven确认 mysql-connector-j 和 druid 两个依赖已下载 # 4. 运行 Main 或 LoginFrame 类这里要特别注意db.properties 里的 url 中 host 建议写 127.0.0.1不要写 localhost。原因是某些 MySQL 安装会默认把 localhost 解析为 socket 连接Unix 系统或 IPv6而 JDBC 的 TCP 连接如果主机名解析异常会报「Cant connect to local MySQL server through socket」错误。写 127.0.0.1 强制走 TCP可以绕开这个坑。启动后如果界面出来了但操作报中文乱码就在 IDE 的启动参数里加-Dfile.encodingUTF-8IDEA 里是 VM options。这个坑特别普遍数据库里的数据是正常中文Java 端读出来变成问号十有八九是 IDE 默认用了 GBK 编码启动 JVM。5. 常见问题排查从 2002 socket 错误到中文乱码的 4 个必查项5.1 现象连接报 error 2002 (HY000): Cant connect to local MySQL server through socket这个问题在热搜词里出现频率很高期末项目里遇到的概率也不小。现象是双击运行项目时控制台抛出这个异常但用 Navicat 或命令行却连不上或者只有 Java 代码连不上。原因是 MySQL 客户端默认走 Unix socket 文件Linux/macOS或命名管道Windows而你的 Java 程序通过 JDBC 驱动发起的是 TCP/IP 连接。两个连接方式路径不同未必都开放。解决方法是分三步走先确认 MySQL 服务确实在跑Windows 服务管理器或net start能看到 mysql 服务再用命令行测试 TCP 连接是否可用命令是mysql -u root -p -h 127.0.0.1 -P 3306如果这条能连上而 Java 连不上说明 Java 的 url 里 host 或 port 写错如果命令行也报 2002说明 MySQL 的 skip-networking 选项被启用了去 my.ini 里把 skip-networking 注释掉重启服务。5.2 现象中文数据写入数据库后变成问号或乱码这个坑几乎是每个期末项目都会遇到的。现象分两种从界面输入中文点保存数据库里变成 ??或者数据库里正常的中文读到界面变成 ??。前一种是写入时编码不匹配后一种是读取时编码不匹配。原因涉及三层编码必须一致MySQL 数据库字符集、JDBC url 的 characterEncoding 参数、Java 工程文件本身的编码。解决方法是三层全部对齐到 UTF-8。具体操作建库时用CREATE DATABASE library DEFAULT CHARACTER SET utf8mb4上面已经做了JDBC url 末尾加characterEncodingutf8上面也已经做了IDEA 里在 Settings → Editor → File Encodings 把 Global Encoding、Project Encoding、Properties Files 都设为 UTF-8。如果项目已经写入了乱码数据用命令行DELETE掉重新插入因为已存在的 ?? 数据不会被自动修复。一个容易漏掉的点如果 db.properties 文件本身是在 Windows 记事本里编辑保存的可能默认用了 ANSI 编码里面如果有中文注释或中文密码也会引发编码错乱。建议用 IDEA 或 VS Code 打开属性文件编辑并保存为 UTF-8 格式。5.3 现象连接池初始化失败报 ClassNotFoundException: com.mysql.cj.jdbc.Driver报这个错说明 mysql-connector-j 的 jar 包没有进入运行时 classpath。期末项目用 Maven 的话检查 pom.xml 依赖是否正确声明然后执行 mvn clean 再重新运行。最常见的原因依赖的作用域写错了。以下是标准依赖声明scope 写 runtime 而不是 compile因为 JDBC 驱动只需要运行时加载编译期不需要引用它。dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId version8.0.33/version scoperuntime/scope /dependency dependency groupIdcom.alibaba/groupId artifactIddruid/artifactId version1.2.20/version /dependency这里有个版本坑mysql-connector-j 的 groupId 在 8.x 版本是 com.mysqlartifact 是 mysql-connector-j而在 5.x 是老坐标 mysql:mysql-connector-java。如果你在网络上复制粘贴了旧版依赖到新项目会下载失败或下载到一个不兼容的旧包。优先用 8.0.33 这个稳定版本它在中央仓库可以正常拉取。如果不用 Maven、直接用 IDEA 的 Project Structure 导入 jar 包检查是否同时导入了 mysql 驱动和 druid 两个包漏掉 druid 会报 DruidDataSourceFactory 找不到。导入后要在 Artifacts 里确认 Output Layout 的 lib 目录下出现了这两个 jar否则编译通过但运行时照样 ClassNotFoundException。5.4 现象数据库连接成功但 SQL 执行报「Unknown column 字段名」这个报错背后的原因多半是 Java 实体类字段名和数据库列名不一致或者 SQL 里查的列在表里不存在。我之前见过一个学生把 book 表的 book_name 字段命名为 bookName查询时写 SELECT bookName FROM bookMySQL 报错找不着列。数据库命名习惯和 Java 驼峰命名本身就是两套体系这个差异要刻意处理。解决方式两种第一种是 SQL 里用别名对齐比如SELECT book_name AS bookName FROM book第二种是用 Map 封装结果而不建实体类。期末项目我推荐第一种因为实体类更接近「面向对象」的要求答辩时好讲。排查步骤是把报错信息里完整的 SQL 语句拷贝出来到 Navicat 或命令行里手动执行一次看是否报同样的错。如果手动执行正常而 Java 执行报错就检查是不是用了不同的数据库比如代码连接的是 library_test 表结构是旧的忽略这个步骤会让你浪费很多时间。5.5 现象时间字段显示「2026-08-24」而不是本地时间出现这个现象的原因通常是 JDBC url 里没有指定 serverTimezone或指定了错误的时区。MySQL 的 CST 时区是一个有歧义的缩写在中国代表北京时间在数据库驱动解析时却可能被当作美国中部时间导致时间偏移 13 个小时。解决方法是把 serverTimezone 显式设为 Asia/Shanghai或者使用serverTimezoneGMT%2B8也行。如果项目里用了返回时间戳的 SQL 函数如 NOW()数据库服务器时间和应用服务器时间可能不一致最稳妥是数据库和 Java 都统一用系统默认时区然后 JDBC url 里显式指定。另外Swing 的 JTable 显示时间时如果你直接把 java.sql.Timestamp set 进表格模型显示格式会丑而且可能带毫秒建议在实体类里把时间字段格式化为yyyy-MM-dd HH:mm:ss字符串再放到表格里展示保存时再转回 Timestamp。这个格式转换看起来多余实际上是让界面专业感提升最明显的小改动。6. 从「能跑」到「像样」演示视频录制、文档组织与答辩留一手项目做到能跑只完成了一半期末大作业的评分很大程度取决于你交付的「完整版」里那三样东西文档、演示视频、安装教程视频。先说文档别写成长篇大论的功能罗列我按答辩被提问的顺序组织成五段需求分析你解决了什么问题、数据库设计ER 图和表结构说明、系统架构Swing/JSPDAOMySQL 三层图、核心代码说明连接池、事务、PreparedStatement 各贴一段关键代码并解释、测试与运行说明环境版本、启动步骤、测试数据。这五段每段控制在两页以内整份文档 15 页左右。演示视频的录制有一个实用技巧不要一上来就操作界面先把数据库表结构 SHOW 一遍再开始演示。具体顺序建议用命令行SHOW TABLES和DESC book;展示表结构说明这是你设计的核心启动项目登录新增一本图书模拟借书流程选书 → 库存减一 → 生成一条借阅记录模拟还书流程查询逾期列表并把一条逾期记录的状态展示出来最后进数据库用 SELECT 验证库存和借阅记录确实变了。录到「数据库数据也跟着变」这一步评分老师就能看出这不是写死的前端假数据。安装教程视频比演示视频更重要因为评分老师很可能看完演示后想自己跑一遍。录制时从「安装 MySQL」讲到「用 source 导入 SQL 脚本」再到「IDEA 打开项目改 db.properties」最后「运行」录之前先把所有步骤走通防止录到一半发现某步报错尴尬。录制工具用 OBS 就行免费而且能同时录屏幕和麦克风分辨率设为 1920x1080保证代码清晰可读。视频时长控制在 12 分钟以内超过的部分八成是无意义停顿和重复操作。最后一个答辩经验在代码里故意留一个「能讲清楚但不算 bug」的设计点。比如我在事务代码里用「UPDATE book SET stock stock - 1 WHERE id ? AND stock 0」这种带库存判断的写法老师问「为什么这里多一个 AND 条件」你回答「为了防止库存被减成负数这也是乐观锁的一种实现」。这种细节比你能背出八个设计模式更能证明代码是你自己写的因为它像一个真实的工程决策而不是教材练习。我把这个习惯沿用了很多年任何期末项目或课程设计交付前一定把「删除关键代码会不会立刻报错」当作测试标准。演示时老师偶尔会让你改一行代码或加一个功能如果系统被你自己的改动弄挂不是能力的证明是交付流程的漏洞。这个项目能给你的不只是学分更是「从零搭起一个完整 CRUD 系统的熟悉感」——那是面试前最有价值的一次实战排练希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →