ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

学生信息管理系统MySQL版源码解析:从建表到JDBC实战

学生信息管理系统MySQL版源码解析:从建表到JDBC实战 简介这是一份基于Java GUI与MySQL的学生信息管理系统完整源码面向Java初学者及需要完成课程设计、毕业设计的开发者覆盖学校信息设置、状态栏配置、登录注册、密码修改以及学生信息的增删改查和分类统计等常见业务功能。压缩包共246个文件其中49个Java源文件对应各功能模块176个class为编译产物sql脚本用于初始化数据库chm帮助文档可离线查阅整体仅1.74MB。目前已有1327人学习下载适合快速掌握Swing布局、DAO模式及JDBC操作。源码按界面类、数据访问接口与实现类分层组织并配有数据库脚本和帮助文档。读者可借此理解登录校验、按学号/姓名/班级/系部查询、多条件统计等典型实现思路直接用于课程设计或项目二次开发。1. 学生信息管理系统(MySQL版)V1.0源码.rar它到底是什么、适合谁用如果你在下载站、网盘或课程设计资源包里翻到过这个文件名大概率会先纠结两件事这个压缩包里的代码能不能直接跑起来以及它是不是又一个改了名字的Java课程设计。我的看法是Student Information Management SystemMySQL版V1.0这类源码包本质上就是一套围绕MySQL数据库的增删改查脚手架——学生表、课程表、成绩表是核心三件套再加上登录鉴权和基本的界面。它解决的是“数据库原理学完了但不知道怎么串成系统”的断层问题多数V1.0里虽然不会有什么高并发、分布式的东西但作为第一个能连数据库、能录入查询的完整项目它的价值在于让你看清一个业务系统从SQL到界面再回到SQL的完整闭环。这套源码最适合三类人碰正在做Java课程设计但不想从零写DAO层的在校生要交数据库大作业、需要一份能跑通MySQL 5.7/8.0的参考工程的求学者以及第一次想搞懂“JDBC到底怎么连接真实数据库”的初学者。别指望它有什么惊艳的架构通常就是标准的JDBC直连模式配db.properties配置文件、工具类封装连接、DAO层写增删改查。本篇我就按这套最常见的技术栈把这类源码从表结构到运行部署拆开讲让你拿到手能改、能跑、能交差。2. 拆开压缩包先看什么V1.0的库表设计与SQL脚本落地学生信息管理系统的MySQL版源码核心资产往往不是Java代码而是那几份SQL脚本。V1.0通常不会用存储过程或视图炫技而是老老实实的建库建表语句加少量测试数据。先看表结构再看数据关系最后才能理解代码里那些SELECT、JOIN往哪张表上打。2.1 学生信息管理系统必备的5张核心表字段设计与关系我见过的学生信息管理系统源码表结构大体逃不出这张关系网学生表student、学院表college/department、课程表course、成绩表score、用户表user。这是最小可行集V1.0一般也就到这里。如果压缩包里出现了班级表class或教师表teacher那是加了权限或排课功能的扩展版但核心依然绕不开上面五张。字段设计上老源码有个很典型的风格——主键用int自增而不是UUID或雪花ID。这么做的原因很简单课程设计阶段不需要分布式IDint自增能直接看到规律而且外键关联写起来一目了然。学生表以学号student_id为主键还是以自增id为主键取决于作者的偏好但我建议你拿到源码后优先改成学号为业务主键因为这是真实业务里查询学生信息的唯一稳定入口。别用姓名做关联重名会让你在成绩表里翻车。MySQL版本上需要注意SQL语法的差异。如果压缩包内的建表语句写得比较早你可能会看到ENGINEMyISAM这样的字样这在MySQL 5.5时代的课程设计里很常见。如果你本地装的是8.0版本跑这种脚本大概率不会报错因为MyISAM引擎还在但外键约束和事务支持会被悄悄忽略掉。更常见的问题是DEFAULT值写法比如“mysql设置默认值为0”这类需求5.7之前可以直接DEFAULT 08.0里同样是这个写法但如果在NOT NULL字段上没写默认值严格模式就会直接拒绝插入。性别字段这个看似简单的地方反而是坑最密集的。一部分源码用CHAR(1)存“男”、“女”另一部分用TINYINT存0和1。如果你要对接后续的统计报表建议直接用TINYINT加注释别用枚举。枚举在MySQL里加成员要ALTER TABLE在Java里映射也麻烦。2.2 从零复制一份可用的建库脚本DDL与初始数据注意事项拿到源码包后不要急着导入整个.sql文件。我的一般做法是先在MySQL里手工建一个空库再按自己的理解跑一遍核心表的DDL最后再对比源码里的脚本看看自己漏了什么。这个过程能帮你快速定位这份源码的表结构设计水平也方便后续改动字段类型时不至于被原有脚本绑死。-- 学生信息管理系统 MySQL版 V1.0 建库脚本手工复刻版 CREATE DATABASE IF NOT EXISTS student_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE student_db; -- 学院表 CREATE TABLE college ( college_id INT AUTO_INCREMENT PRIMARY KEY COMMENT 学院ID, college_name VARCHAR(50) NOT NULL COMMENT 学院名称 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学院表; -- 学生表 CREATE TABLE student ( student_id VARCHAR(20) PRIMARY KEY COMMENT 学号, student_name VARCHAR(30) NOT NULL COMMENT 姓名, gender TINYINT NOT NULL DEFAULT 1 COMMENT 性别 1男 0女, birthday DATE NULL COMMENT 出生日期, college_id INT NOT NULL COMMENT 所属学院ID, enroll_year YEAR NULL COMMENT 入学年份, phone VARCHAR(20) NULL COMMENT 联系电话 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学生表; -- 课程表 CREATE TABLE course ( course_id INT AUTO_INCREMENT PRIMARY KEY COMMENT 课程ID, course_name VARCHAR(50) NOT NULL COMMENT 课程名称, credit DECIMAL(3,1) NOT NULL DEFAULT 2.0 COMMENT 学分 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT课程表; -- 成绩表 CREATE TABLE score ( id INT AUTO_INCREMENT PRIMARY KEY, student_id VARCHAR(20) NOT NULL, course_id INT NOT NULL, score DECIMAL(5,2) NULL COMMENT 成绩, exam_date DATE NULL COMMENT 考试日期, UNIQUE KEY uk_stu_course (student_id, course_id), CONSTRAINT fk_score_student FOREIGN KEY (student_id) REFERENCES student(student_id), CONSTRAINT fk_score_course FOREIGN KEY (course_id) REFERENCES course(course_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT成绩表; -- 用户表登录用 CREATE TABLE user ( user_id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(30) NOT NULL UNIQUE COMMENT 登录名, password VARCHAR(64) NOT NULL COMMENT 密码V1.0多半是明文或MD5, role TINYINT NOT NULL DEFAULT 1 COMMENT 角色 0管理员 1普通用户 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表;这段DDL比源码包里常见的版本多做了两件事一是所有字段都加了COMMENT这在MySQL 5.7之后能直接通过information_schema查出来结对编程和写实验报告时省事二是字符集统一用utf8mb4而非utf8否则插入emoji昵称或生僻字会直接报“Incorrect string value”错。字段类型上enroll_year用YEAR而不是VARCHAR是为了后面按月查询“2024级学生”时能直接用BETWEEN。外键要不要建是个值得纠结的点。我建议在成绩表上建物理外键因为学生信息管理系统最典型的成绩录入场景里外键能挡掉“给不存在的学生录成绩”这类脏数据。但是——如果你打算拿这套源码做性能压测或者以后拆微服务物理外键反而是负担那时候就把约束写在应用层。V1.0阶段建上没坏处。初始数据那一块源码包常犯的毛病是只给两条测试学生记录一旦你切换到分页查询看起来就像死机。我会在建库后顺手写一个存储过程批量生成几百条模拟学生数据后面调试列表页和搜索功能时才知道自己的SQL到底有没有写对。3. 源码能否跑起来的关键MySQL连接配置与JDBC层代码骨架表结构只是地基V1.0这份源码的主角其实是连接数据库的那一层代码。很多初学者下载源码后卡在第一步——启动程序后报ERROR 2002 (HY000): Cant connect to local MySQL server through socket /tmp/mysql.sock然后直接放弃。这类问题十有八九不是代码错而是MySQL服务的连接方式、端口、账号密码没对齐。3.1 db.properties五要素端口、编码、useSSL、时区与驱动版本几乎每一份学生信息管理系统源码都会带一个db.properties配置文件少数老古董把它写死在DBUtil.java里。后者的做法不可取因为换环境就得改代码重新编译。V1.0版本的配置项通常就是下面这几行但细节上的坑能写满半页笔记# db.properties - MySQL连接配置5.7与8.x通用写法 jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/student_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue jdbc.usernameroot jdbc.passwordyour_password jdbc.pool.maxActive10 jdbc.pool.initialSize2这里每一行都有讲究。第一行com.mysql.cj.jdbc.Driver是MySQL 8.x的驱动类名老源码里如果写的是com.mysql.jdbc.Driver在8.0驱动下会有一行过时警告但能跑在驱动版本mysql-connector-java8.0.11以上才推荐换成cj。useSSLfalse非常重要8.0默认会尝试开启SSL连接本地开发环境没有配证书直接报“SSL connection error”加上就安静了。serverTimezoneAsia/Shanghai是处理“时区”报错的关键——不写这个连接MySQL 8.x大概率会遇到The server time zone value йʱ is unrecognized中文乱码区时区提示。allowPublicKeyRetrievaltrue是8.0后另加的否则用caching_sha2_password插件验证用户身份时会有一次性公钥获取失败的情况。连接池那两行参数V1.0源码里经常没有是后来加上的。早期课程设计就是DriverManager.getConnection()裸连每次操作数据库都经历“建立连接-执行SQL-关闭连接”三步并发上来后连接数飙升很能把MySQL压垮。如果你拿到源码里没有什么连接池直接补上DBCP或HikariCP的依赖即可。需要留意的是连接池的最大连接数应与MySQL的max_connections匹配默认15110以内足够学生系统这种量级。3.2 从DBUtil到DAO一次查询的完整生命周期理解了配置文件接下来看代码层是如何消费这份配置的。我复刻的这套源码结构通常分三层DBUtil负责拿连接StudentDao负责SQL操作StudentService负责事务与业务判断。下面这段就是从学生表按学号查询的最朴素写法老源码爱用我也觉得作为模板够直白// DBUtil.java - 连接工厂 public class DBUtil { private static String url; private static String username; private static String password; static { try (InputStream in DBUtil.class.getClassLoader() .getResourceAsStream(db.properties)) { Properties props new Properties(); props.load(in); Class.forName(props.getProperty(jdbc.driver)); url props.getProperty(jdbc.url); username props.getProperty(jdbc.username); password props.getProperty(jdbc.password); } catch (Exception e) { throw new ExceptionInInitializerError(数据库配置加载失败); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, username, password); } }这段静态代码块保证了DBUtil只在类加载时读一次配置后续所有并发请求复用同一个Properties对象没有同步负担。用try-with-resources读配置文件是Java 7之后的规范写法省掉了手动关闭InputStream的麻烦。Class.forName在JDBC 4.0之后可以省略但保留它能让代码对早期驱动更友好。// StudentDao.java - 按学号查询PreparedStatement版 public Student findById(String studentId) { String sql SELECT student_id, student_name, gender, college_id, enroll_year FROM student WHERE student_id ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, studentId); try (ResultSet rs ps.executeQuery()) { if (rs.next()) { Student stu new Student(); stu.setStudentId(rs.getString(student_id)); stu.setStudentName(rs.getString(student_name)); stu.setGender(rs.getInt(gender)); stu.setCollegeId(rs.getInt(college_id)); stu.setEnrollYear(rs.getInt(enroll_year)); return stu; } } } catch (SQLException e) { e.printStackTrace(); } return null; }这里必须用PreparedStatement而不是Statement拼字符串四个字防SQL注入。比如学生登录框里输入 OR 11如果你用Statement直接拼SQL整个表都能查出来这在学生信息管理系统里属于最低级的漏洞但市面上V1.0源码里还真有不少这么写的。ps.setString(1, studentId)这个位置参数的好处还能体现在MySQL的预编译缓存上相同的SQL结构在MySQL端有缓存相当于白拿一次性能优化。查询完一定要在finally里关闭连接吗我的习惯是能用try-with-resources就用关闭顺序按ResultSet、PreparedStatement、Connection反序来。连接池场景下conn.close()并不会真断开MySQL只是归还连接但如果用裸连的情况下不关连接会一直挂着直到超时熔断。3.3 写操作的事务边界批量录入成绩别半路断电查询相对简单写入操作就要严肃点对待事务了。很多V1.0源码对事务的写法是——压根不写。单条INSERT就算失败也只回滚那一句但如果业务是“录入一个学生的五门课成绩”需要往成绩表插五条记录中间第四条失败前面三条就留了一半这种脏数据在期末成绩单上会显示成“五门课只有三门有分”。// ScoreService.java - 批量录入成绩带事务控制 public boolean saveScores(String studentId, MapInteger, Double courseScores) { String sql INSERT INTO score (student_id, course_id, score, exam_date) VALUES (?, ?, ?, CURRENT_DATE) ON DUPLICATE KEY UPDATE score VALUES(score); Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 手动开启事务 try (PreparedStatement ps conn.prepareStatement(sql)) { for (Map.EntryInteger, Double entry : courseScores.entrySet()) { ps.setString(1, studentId); ps.setInt(2, entry.getKey()); ps.setDouble(3, entry.getValue()); ps.addBatch(); // 攒一批再执行 } ps.executeBatch(); } conn.commit(); // 全部成功才提交 return true; } catch (SQLException e) { if (conn ! null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } return false; } finally { if (conn ! null) { try { conn.setAutoCommit(true); conn.close(); } catch (SQLException e) { } } } }这个写法比提前写好的多值INSERT更灵活因为成绩可能分批录入批次之间不会互相覆盖。addBatchexecuteBatch是性能关键一次网络往返提交一批而不是每门课一个round-trip。ON DUPLICATE KEY UPDATE的作用是应对重修补录的成绩——同一学号同一课程已经存在记录时直接覆盖分数而不是再插一行导致后面统计平均分时算出两份权重。事务在MySQL里能够生效的前提是表引擎为InnoDB。如果你建库脚本里是MyISAM上面的代码就像打在棉花上——MyISAM压根不支持事务执行rollback()不会有任何作用。这也是我建议拿到源码后第一时间确认各表引擎的原因。4. 跑通全流程的典型踩坑MySQL安装、连接与运行期报错排查别小看“能跑起来”这三个字我在帮别人看这份源码时遇到过的问题按频率排序大概是这样MySQL服务没启动、驱动版本不匹配、useSSL时区报错、端口3306被占用、root密码对不上、SQL脚本导入乱码。下面挑最有代表性的几个每条都按现象、原因、解决写清楚方便你直接对号入座。4.1 现象ERROR 2002 (HY000)连不上本地MySQL原因服务没起或socket路径不对这是MySQL安装后最常见的拦路虎。你按网上教程装好了MySQL但用命令行mysql -u root -p登录时报错Cant connect to local MySQL server through socket /tmp/mysql.sock。这个错在Linux和macOS上特别多见原因是MySQL服务端进程没启动客户端在/tmp下找不到socket文件。Windows上则多半表现为ERROR 2003因为走的是TCP 3306端口而不是socket。解决分三步先确认服务是否在运行系统服务管理器里查mysqld再确认socket文件的实际路径不同安装方式可能落在/var/run/mysqld/mysqld.sock或/tmp/mysql.sock最后用TCP方式连接绕过socket命令加-h 127.0.0.1 -P 3306。如果是Linux上通过apt或yum安装的MySQL服务名可能是mysqld也可能是mysql用systemctl status mysql看一眼没起来就systemctl start mysql。4.2 现象useSSL警告刷屏/连接被拒绝原因MySQL 8.x与驱动默认行为变化代码和环境都没动过换了一台电脑就启动失败日志里一片SSL connection error这就很可能是MySQL版本差异。MySQL 8.x默认启用SSL而旧驱动或配置里没显式设置useSSL参数时握手阶段就会出问题。另一个常见情况是日志里报Public Key Retrieval is not allowed这是因为8.0默认认证插件是caching_sha2_password在非SSL连接下需要先获取服务器公钥。解法和配置都写在上面的db.properties里URL中显式加useSSLfalse和allowPublicKeyRetrievaltrue。前者关掉SSL握手后者允许客户端向服务器要公钥做密码加密传输。如果公司安全规定不允许关SSL那就替换驱动到8.0以上的mysql-connector-j版本并在服务器上配好证书但这已经超出课程设计范畴了。4.3 现象导入SQL脚本后中文全是问号/乱码原因客户端、连接、表三方字符集不一致字符集乱码是学生信息管理系统里最阴魂不散的问题。你可能把建库脚本用source命令导进MySQL表里student_name这一列存的数据在Java界面显示正常但直接到MySQL命令行查就变成???。原因通常是三层字符集没对齐操作系统终端编码、MySQL客户端连接编码、服务器端库表编码。解决思路是统一到utf8mb4。导入前先执行SET NAMES utf8mb4;这会让本次会话的客户端编码和连接编码切到utf8mb4建库时已经写了DEFAULT CHARACTER SET utf8mb4的表不受影响如果库表已经建好但编码不对用ALTER DATABASE student_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;和对应表的ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4;来修。Windows下如果你用cmd导入建议先chcp 65001切到UTF-8代码页否则source的批处理文件会按GBK读。4.4 现象端口3306被占用导致MySQL起不来原因残留进程或别的软件抢占这个比较隐蔽你systemctl start mysql后也没报错但Java程序连接时提示Connection refused。查netstat -tlnp | grep 3306发现端口被pid为xxx的进程占着但ps -ef | grep xxx看到的不是mysqld而是另一个MySQL实例的守护进程。常见于以前用压缩包版MySQL手动启动过后来又要用系统服务版两个实例抢同一个端口。解决思路很简单找到真正要用的那个实例把另一个停掉或者给其中一个换端口。如果你不太确定当前哪个是“正确的”就先mysql -u root -p试着登录看一眼select port;能登录的那个实例就是正在监听的端口对应的那个。也可以在my.cnf里改一个业务专用端口比如3307这样Java的jdbc.url要跟着改端口配置文件里是有这个值的。4.5 现象代码在原来电脑跑得好好的新环境装完MySQL就是连不上原因账号密码与root远程访问权限很多源码包里的db.properties写的是jdbc.usernameroot和jdbc.password123456但你自己装的MySQL初始root密码是随机生成的临时密码两者对不上。MySQL 5.7之后的首次安装不再默认无密码会生成一个临时密码放进错误日志你需要先找到它并登录修改。另一个场景是MySQL账号支持本机socket连接但JDBC走TCP连接时被拒因为在mysql.user表里root可能只允许localhost访问。解决放一起说确定要用的root密码后执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码;把插件换成mysql_native_password可以少碰caching_sha2_password的兼容问题。如果JDBC的URL用的是127.0.0.1而不是localhost还需要确认有没有root127.0.0.1这个账号没有就创建一个或者直接用root%开发环境授权。5. 把V1.0的代码改出进阶质感PreparedStatement防注入与搜索参数化落地前面几段已经覆盖了跑通整条链路所需的基础操作但如果你想让这份源码在课程设计答辩里显得有“工程感”那就不能停在“能连上、能查询”的原生状态。这个版本的很多代码是典型的“学生时代风格”登录验证直接从ResultSet里比对字符串搜索框拿用户输入直接拼LIKE语句密码以明文方式存进db。下面这几处改动是投入产出比最高的进阶操作不会改变V1.0的结构但会让它更像一份及格的软件作品。5.1 登录模块的三宗罪明文密码、拼串查询、无防暴力破解登录功能是学生信息管理系统的门面也是老外代码问题最密集的地方。第一宗罪是密码明文存储数据库里password字段直接是123456一旦数据库泄露全部账号裸奔最小改动是用MD5加盐后存储。第二宗罪是查询用Statement直接拼接用户名和密码存在SQL注入漏洞。第三宗罪是登录没有失败次数的限制默认可以无限重试这是给暴力破解留后门。改进密码存储的步骤不复杂注册时把用户输入的密码做MD5(密码 固定盐值)再落库登录时对输入做同样处理后比对。盐值不需要每个用户单独随机的复杂体系课程设计阶段用一个常量盐就够了实际生产环境必须用BCrypt或PBKDF2但V1.0场景下MD5加盐已经能挡住绝大多数“一眼看到密码”的尴尬。防暴力破解可以在user表加一个fail_count字段登录失败就更新连续失败五次锁定账号15分钟这是非常轻量的方案。5.2 LIKE查询的参数占位搜索学生姓名时别用百分号拼串学生信息管理系统最常被人点开的功能是学生列表和条件搜索“按姓名模糊查询”几乎必做。老代码里常这样写SELECT * FROM student WHERE student_name LIKE % keyword %。这玩意在代码评审里会被一眼盯上——不仅是注入风险还让MySQL没法用索引因为前导通配符%会强制全表扫描。如果学生表数据量过千搜索一次就把连接池拖满的情况完全可能发生。改法是改用PreparedStatement把%通配符放到参数里而不是拼进SQL字符串// StudentDao.java - 姓名模糊查询参数化安全写法 public ListStudent searchByName(String keyword) { String sql SELECT student_id, student_name, college_id, enroll_year FROM student WHERE student_name LIKE ? ORDER BY student_id LIMIT 100; ListStudent result new ArrayList(); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, % keyword %); // 通配符作为参数值传入 try (ResultSet rs ps.executeQuery()) { while (rs.next()) { Student stu new Student(); stu.setStudentId(rs.getString(student_id)); stu.setStudentName(rs.getString(student_name)); stu.setCollegeId(rs.getInt(college_id)); stu.setEnrollYear(rs.getInt(enroll_year)); result.add(stu); } } } catch (SQLException e) { e.printStackTrace(); } return result; }这里把%放在setString的参数值上而不是拼在SQL里MySQL的预编译机制就会把这个LIKE ?当模板缓存起来后续不同关键字都复用执行计划。加了LIMIT 100是为了防止学生数据量膨胀后一次查询把列表页撑爆同时能配合前端分页。有个细节要注意如果用户搜索的关键词本身包含%或_这两个字符在LIKE里有特殊含义严谨的写法需要用ESCAPE语法转义比如LIKE ? ESCAPE \\课程设计里可以先忽略但答辩时被问到要能讲清楚。5.3 JDBC批量导入学生数据的正确姿势从逐条插入到批量提交还有一个常见升级点是Excel批量导入学生名册。V1.0源码通常只有单条插入如果从教务系统导出一千个学生界面要插一千次每次都得单独走一轮网络往返和事务日志刷盘。换成addBatchexecuteBatch后一千条INSERT会打包成少数几次网络包提交时间从分钟级降到秒级而且源码结构不变就是在循环里攒批。// StudentService.java - 批量导入学生批量提交版 public int importStudents(ListStudent students) { String sql INSERT INTO student (student_id, student_name, gender, birthday, college_id, enroll_year, phone) VALUES (?, ?, ?, ?, ?, ?, ?); Connection conn null; int successCount 0; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); try (PreparedStatement ps conn.prepareStatement(sql)) { for (int i 0; i students.size(); i) { Student s students.get(i); ps.setString(1, s.getStudentId()); ps.setString(2, s.getStudentName()); ps.setInt(3, s.getGender()); if (s.getBirthday() ! null) { ps.setDate(4, new java.sql.Date(s.getBirthday().getTime())); } else { ps.setNull(4, Types.DATE); } ps.setInt(5, s.getCollegeId()); ps.setInt(6, s.getEnrollYear()); ps.setString(7, s.getPhone()); ps.addBatch(); // 每500条刷一次避免batch太大占用内存 if (i % 500 0 i 0) { ps.executeBatch(); } } ps.executeBatch(); // 刷掉最后不足500条的批次 conn.commit(); } return students.size(); } catch (SQLException e) { try { if (conn ! null) conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } return 0; } finally { try { if (conn ! null) conn.setAutoCommit(true); } catch (SQLException e) { } } }注意ps.setNull处理可空字段的写法很多老源码对birthday直接不填导致插入时报Column birthday cannot be null。批处理刷500条一次的设计不是拍脑袋——MySQL默认max_allowed_packet是64MB但过大的batch会让PreparedStatement持有的参数缓存占用较多堆内存500到1000是一个稳妥的区间。改完之后用两万条模拟数据压一下你会发现性能差距肉眼可见。技术之外的最后一件事这份V1.0源码通常会配一个说明文档或ReadMe但要么是空壳要么是复制粘贴的通用模板所以不要把运行步骤寄托在文档上环境对不上时靠的还是上面这几条兜底能力。从建库到连接池从防注入到批量导入每拨一层都是在把“能交差的作业”变成“能拿得出手的作品”的过程。希望这份踩过坑换来的顺序能帮到你愿你拿到任何一份学生信息管理系统源码都能第一步跑通、第二步改优、第三步从容答辩。本文还有配套的精品资源点击获取
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表