恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
通讯录管理系统数据库课程设计:从建表到Java增删改查完整落地
首页
资讯中心
/
通讯录管理系统数据库课程设计:从建表到Java增删改查完整落地
通讯录管理系统数据库课程设计:从建表到Java增删改查完整落地
发布时间:2026/10/12 3:13:53
简介这份通讯录管理系统数据库课程设计报告面向高校数据库原理与应用课程的学习者与课程设计参与者帮助解决从需求分析到系统实施全流程的文档撰写与设计参考问题。资源包内含1个docx文档压缩包约840KB内容以课程设计报告为主体涵盖需求分析、概念结构设计、逻辑设计、数据库实施及运行维护等章节。报告以SQL Server为存储、JAVA构建界面完整呈现用户登录、联系人增删改查、分组管理等功能的实现思路并附有E-R图、数据字典、关系模式优化及建库建表、视图与存储过程代码。目前已有74人学习适合需要参考课程设计结构、梳理数据库设计步骤或准备类似项目的学生可据此理解实体关系建模、函数依赖分析与界面模块划分为实际开发与报告撰写提供可借鉴的完整范例。1. 通讯录管理系统数据库课程设计从建表到交报告的完整落地路径每年期末总有一批人对着“通讯录管理系统数据库课程设计报告.docx”这个文件名发愁。课设本身不难难的是把数据库设计、Java 增删改查、报告文档三件事串成一条线最后交上去还能经得起老师追问“你的索引为什么这么建”。我做过也带人做过不少这类课设最常见的翻车点不是代码写不出来而是表结构一开始就设计歪了后面 Java 代码越写越别扭报告里也讲不清范式。这篇笔记就按一线做法把通讯录管理系统从需求拆解、SQL Server 建库建表、Java 连接实现增删改查到报告里该写什么、哪些坑必须提前避开完整走一遍。适合正在做数据库课程设计、软件工程课程设计或者想拿一个完整小项目练手 SQL Server 和 Java 基础的人。2. 需求拆解与表结构设计通讯录到底该建几张表2.1 先想清楚通讯录管理系统的实体和关系很多人一上来就CREATE TABLE contact把姓名、电话、邮箱、分组、备注全塞一张表。这样写能跑但报告里一写“数据库设计”就露怯。通讯录管理系统的核心实体通常有三个联系人、分组、用户如果做登录。联系人属于某个分组一个分组下有多个联系人这是一对多。如果还要记录每个联系人的多个电话号码手机、座机、工作电话那就再拆一张电话表变成一对多。课程设计里我一般建议至少拆成三张表users、groups、contacts。如果时间充裕再加一张phones表体现多值属性报告里能多写一段“为什么要拆表”的分析。为什么强调拆表因为数据库课程设计评分里表结构设计占很大比重。老师看的是你有没有理解第一范式、第二范式、第三范式。把分组名直接存在联系人表里就存在传递依赖不满足 3NF。拆出groups表之后contacts表里只存group_id分组改名时不用更新所有联系人记录这就是拆表的实际收益报告里也能写成设计理由。2.2 SQL Server 建库建表的完整脚本下面这套脚本可以直接在 SQL Server Management Studio 里执行。我一般会先建库再建表最后插测试数据。注意字段类型选择姓名用NVARCHAR支持中文电话用VARCHAR因为不需要中文日期用DATETIME默认GETDATE()。-- 建库 CREATE DATABASE ContactBook; GO USE ContactBook; GO -- 用户表 CREATE TABLE users ( user_id INT IDENTITY(1,1) PRIMARY KEY, username NVARCHAR(50) NOT NULL UNIQUE, password NVARCHAR(100) NOT NULL, create_time DATETIME DEFAULT GETDATE() ); -- 分组表 CREATE TABLE groups ( group_id INT IDENTITY(1,1) PRIMARY KEY, group_name NVARCHAR(50) NOT NULL, user_id INT NOT NULL, CONSTRAINT fk_group_user FOREIGN KEY (user_id) REFERENCES users(user_id) ); -- 联系人表 CREATE TABLE contacts ( contact_id INT IDENTITY(1,1) PRIMARY KEY, name NVARCHAR(50) NOT NULL, phone VARCHAR(20) NOT NULL, email NVARCHAR(100), address NVARCHAR(200), remark NVARCHAR(500), group_id INT, create_time DATETIME DEFAULT GETDATE(), CONSTRAINT fk_contact_group FOREIGN KEY (group_id) REFERENCES groups(group_id) ); -- 索引按姓名和电话查询是高频操作 CREATE INDEX idx_contact_name ON contacts(name); CREATE INDEX idx_contact_phone ON contacts(phone);这段脚本里几个关键点IDENTITY(1,1)让主键自增避免手动维护 IDUNIQUE约束保证用户名不重复外键约束保证联系人不会挂到不存在的分组上。索引建在name和phone上因为通讯录最常用的操作就是按姓名搜、按电话搜。报告里可以写“针对高频查询字段建立非聚簇索引提升检索效率”这就是加分项。2.3 测试数据与增删改查验证建完表先插几条数据验证外键和约束是否生效。这一步别省很多人的脚本在别人机器上跑不起来就是因为没做数据验证。-- 插入测试数据 INSERT INTO users (username, password) VALUES (Nadmin, N123456); INSERT INTO groups (group_name, user_id) VALUES (N家人, 1), (N同事, 1), (N同学, 1); INSERT INTO contacts (name, phone, email, group_id) VALUES (N张三, 13800001111, Nzhangsantest.com, 1), (N李四, 13900002222, Nlisitest.com, 2), (N王五, 13700003333, Nwangwutest.com, 3); -- 验证查询 SELECT c.name, c.phone, g.group_name FROM contacts c LEFT JOIN groups g ON c.group_id g.group_id; -- 验证更新 UPDATE contacts SET phone 13800009999 WHERE name N张三; -- 验证删除先删联系人再删分组避免外键冲突 DELETE FROM contacts WHERE contact_id 3;这里用LEFT JOIN而不是INNER JOIN是因为如果某个联系人没分组INNER JOIN会把它过滤掉。课程设计里这种细节最能体现你是否真理解 SQL。删除操作要注意外键顺序先删子表再删父表否则会报外键约束错误。这个坑后面还会细说。3. Java 连接 SQL Server 实现通讯录增删改查3.1 JDBC 连接配置与驱动选择Java 连 SQL Server常见做法是用 Microsoft 官方 JDBC 驱动。注意 SQL Server 2008 和 2012 之后的驱动版本不一样2008 用sqljdbc4.jar2012 以后用mssql-jdbc。我一般会在项目里建一个DBUtil类统一管理连接避免每次写重复代码。import java.sql.*; public class DBUtil { // 注意SQL Server 默认端口 1433实例名不同连接串不同 private static final String URL jdbc:sqlserver://localhost:1433;databaseNameContactBook;encryptfalse; private static final String USER sa; private static final String PASSWORD 你的密码; static { try { Class.forName(com.microsoft.sqlserver.jdbc.SQLServerDriver); } catch (ClassNotFoundException e) { throw new RuntimeException(驱动加载失败检查 jar 包是否导入, e); } } 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(); } catch (SQLException ignored) {} try { if (stmt ! null) stmt.close(); } catch (SQLException ignored) {} try { if (conn ! null) conn.close(); } catch (SQLException ignored) {} } }连接串里encryptfalse在本地开发时常用因为 SQL Server 默认可能要求加密连接不加这个参数容易报 SSL 错误。sa账户需要在 SQL Server 里启用混合验证模式并且确保 TCP/IP 协议已开启。如果连不上先检查 SQL Server 配置管理器里 TCP/IP 是否启用端口是不是 1433。3.2 联系人查询与模糊搜索实现通讯录最核心的功能就是查。下面这段代码实现按姓名模糊搜索返回联系人列表。用PreparedStatement而不是Statement防止 SQL 注入这也是报告里可以写的安全设计点。import java.sql.*; import java.util.*; public class ContactDao { public ListMapString, Object searchByName(String keyword) { ListMapString, Object list new ArrayList(); String sql SELECT c.contact_id, c.name, c.phone, c.email, g.group_name FROM contacts c LEFT JOIN groups g ON c.group_id g.group_id WHERE c.name LIKE ? ORDER BY c.name; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, % keyword %); try (ResultSet rs ps.executeQuery()) { while (rs.next()) { MapString, Object row new HashMap(); row.put(id, rs.getInt(contact_id)); row.put(name, rs.getString(name)); row.put(phone, rs.getString(phone)); row.put(email, rs.getString(email)); row.put(group, rs.getString(group_name)); list.add(row); } } } catch (SQLException e) { e.printStackTrace(); } return list; } }LIKE ?配合ps.setString(1, % keyword %)实现模糊匹配。注意%要拼在 Java 字符串里不能写在 SQL 里否则预编译参数失效。返回ListMap是为了方便后续转 JSON 或直接打印课程设计里够用。如果要做分页可以在 SQL 里加OFFSET ? ROWS FETCH NEXT ? ROWS ONLYSQL Server 2012 以上支持。3.3 新增、修改、删除的完整方法增删改三个操作逻辑类似都是执行executeUpdate返回受影响行数。下面把三个方法写在一起方便对比。public boolean addContact(String name, String phone, String email, int groupId) { String sql INSERT INTO contacts (name, phone, email, group_id) VALUES (?, ?, ?, ?); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, name); ps.setString(2, phone); ps.setString(3, email); ps.setInt(4, groupId); return ps.executeUpdate() 0; } catch (SQLException e) { e.printStackTrace(); return false; } } public boolean updatePhone(int contactId, String newPhone) { String sql UPDATE contacts SET phone ? WHERE contact_id ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, newPhone); ps.setInt(2, contactId); return ps.executeUpdate() 0; } catch (SQLException e) { e.printStackTrace(); return false; } } public boolean deleteContact(int contactId) { String sql DELETE FROM contacts WHERE contact_id ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setInt(1, contactId); return ps.executeUpdate() 0; } catch (SQLException e) { e.printStackTrace(); return false; } }三个方法都用try-with-resources自动关闭连接避免忘记关连接导致连接池耗尽。executeUpdate返回 int大于 0 表示操作成功。删除时如果联系人被其他表引用比如以后加了通话记录表会报外键约束错误这时候要么先删子表记录要么用级联删除。课程设计阶段一般不会遇到但报告里可以提一句“删除策略采用先检查引用再删除”。4. 课程设计报告怎么写才不被老师打回4.1 报告结构从需求到测试的完整链条课程设计报告不是代码说明书老师看的是你的设计思路和验证过程。我一般按这个结构写需求分析、概念设计E-R 图、逻辑设计表结构、物理设计索引和存储、实现关键代码、测试测试用例和结果、总结。E-R 图用 Visio 或 draw.io 画别用截图糊弄。表结构用表格列出来字段名、类型、约束、说明四列清晰明了。测试部分要写具体用例比如“输入姓名‘张’应返回所有姓张的联系人”“删除不存在的联系人 ID应返回失败”。每条用例写输入、预期输出、实际输出。这样老师一看就知道你真跑过不是编的。4.2 报告里必须体现的数据库设计要点报告里一定要有一段讲范式。比如“联系人表中 group_id 作为外键消除传递依赖满足第三范式”。再讲索引设计“在 name 和 phone 上建立非聚簇索引因为通讯录高频操作是查询”。还可以讲安全性“使用 PreparedStatement 防止 SQL 注入”“密码字段不存明文实际项目中应加盐哈希”。这些点写进去报告档次立刻不一样。另外报告里别只贴代码要贴关键代码加解释。比如贴searchByName方法然后说明“使用 LIKE 模糊匹配参数通过 PreparedStatement 传入避免拼接 SQL”。代码块前后要有文字说明不能光秃秃一段代码。4.3 常见格式与内容失分点格式上目录要自动生成页码要连续图表要编号。内容上最常见的失分点是“只有代码没有设计”和“测试数据太少”。我见过有人报告里只插了三条数据测试用例就写“查询成功”这种肯定拿不到高分。至少准备 10 条以上测试数据覆盖增删改查各种边界情况比如空姓名、超长电话、重复用户名。还有一点报告里不要出现“由于时间关系”“功能比较简单”这种话。课程设计就是让你展示能力的自己先泄气老师更不会给高分。5. 避坑与排查通讯录课设里最容易翻车的 5 个地方5.1 现象Java 连不上 SQL Server报“连接被拒绝”原因通常是 SQL Server 的 TCP/IP 协议没启用或者端口不是默认的 1433。SQL Server Express 版默认是动态端口需要手动改成 1433。解决打开 SQL Server 配置管理器展开“SQL Server 网络配置”启用 TCP/IP在 IP 地址选项卡里把 TCP 端口改成 1433重启服务。然后在 Java 连接串里确认端口一致。5.2 现象插入中文变成问号原因是数据库字段用了VARCHAR而不是NVARCHAR或者连接串没指定字符集。解决所有存中文的字段用NVARCHARJava 里字符串前加N前缀如N张三连接串可以加sendStringParametersAsUnicodetrue。SQL Server 的VARCHAR默认按数据库排序规则存储中文可能乱码。5.3 现象删除分组时报外键冲突原因是有联系人还挂在这个分组下。解决先删联系人再删分组或者建外键时加ON DELETE CASCADE但级联删除有风险课程设计里我一般建议手动先删子表。报告里可以写“删除策略采用先检查引用再删除避免级联删除导致误删”。5.4 现象模糊搜索查不到结果原因是LIKE后面的%拼错了位置或者参数没传进去。解决确认 SQL 是LIKE ?Java 里ps.setString(1, % keyword %)。如果还是查不到检查数据库里数据是不是有前后空格可以用TRIM函数处理。5.5 现象报告里的 E-R 图和表结构对不上原因是画图时凭感觉画没和实际建表脚本对照。解决先建表再根据表反向画 E-R 图。实体属性、关系、基数都要和 SQL 脚本一致。画完让同学对着脚本检查一遍这种低级错误在答辩时被指出来很尴尬。6. 进阶技巧用存储过程和事务把课设做出工程味6.1 用存储过程封装批量删除课程设计里如果只写 Java 增删改查显得单薄。加一个存储过程报告里就能多写一节“数据库编程”。比如批量删除某个分组下的所有联系人CREATE PROCEDURE sp_delete_contacts_by_group group_id INT AS BEGIN SET NOCOUNT ON; BEGIN TRANSACTION; BEGIN TRY DELETE FROM contacts WHERE group_id group_id; DELETE FROM groups WHERE group_id group_id; COMMIT TRANSACTION; END TRY BEGIN CATCH ROLLBACK TRANSACTION; THROW; END CATCH END;这个存储过程用事务保证两条删除要么都成功要么都回滚。TRY...CATCH是 SQL Server 的错误处理机制THROW把错误抛给调用方。Java 里用CallableStatement调用{call sp_delete_contacts_by_group(?)}。报告里可以写“使用存储过程封装业务逻辑减少网络传输利用事务保证数据一致性”。6.2 用事务保证 Java 端多表操作一致性如果不用存储过程在 Java 里手动控制事务也行。比如添加联系人时同时更新分组统计字段需要两个 SQL 在一个事务里public boolean addContactWithGroupCheck(String name, String phone, int groupId) { String checkSql SELECT COUNT(*) FROM groups WHERE group_id ?; String insertSql INSERT INTO contacts (name, phone, group_id) VALUES (?, ?, ?); Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 开启事务 try (PreparedStatement check conn.prepareStatement(checkSql)) { check.setInt(1, groupId); try (ResultSet rs check.executeQuery()) { if (rs.next() rs.getInt(1) 0) { conn.rollback(); return false; // 分组不存在 } } } try (PreparedStatement insert conn.prepareStatement(insertSql)) { insert.setString(1, name); insert.setString(2, phone); insert.setInt(3, groupId); insert.executeUpdate(); } conn.commit(); return true; } catch (SQLException e) { try { if (conn ! null) conn.rollback(); } catch (SQLException ignored) {} e.printStackTrace(); return false; } finally { try { if (conn ! null) conn.setAutoCommit(true); conn.close(); } catch (SQLException ignored) {} } }关键点是setAutoCommit(false)开启事务所有操作成功后commit()任何一步失败就rollback()。finally里恢复自动提交并关闭连接。这段代码放进报告老师一看就知道你懂事务不是只会 CRUD。6.3 验证方法用 SQL Server Profiler 看真实执行语句最后分享一个我常用的验证习惯用 SQL Server Profiler 跟踪 Java 程序实际发过来的 SQL。有时候代码里写的和数据库收到的不一样比如参数没绑上、SQL 被截断。Profiler 里新建跟踪选SQL:BatchCompleted和RPC:Completed事件跑一遍 Java 程序看实际执行的语句和参数。这个技巧在排查“为什么查询结果不对”时特别管用也是课程设计答辩时能讲出来的实战经验。做课设这些年我最大的教训就是别等到最后一天才动手建库。表结构一旦定下来后面 Java 代码和报告都是围绕它转的前期多花两小时把 E-R 图和建表脚本对齐后面能省两天返工。希望帮到你。本文还有配套的精品资源点击获取