数据库感觉真的真的太重要了!!!
文章目录
前言
我在做JavaWeb课程设计的学生成绩输入系统时,包括我自己在网上找的家居项目,感觉数据库特别的重要,不管是我们对于Service层的往DAO层的调用 还是数据库把数据封装到实体当中,还是前端页面的显示,我们或多或少都会用到数据库,我感觉到了数据库的强大,下面给大家说说我在基于这些项目中对数据库的看法。
提示:以下是本篇文章正文内容,下面案例可供参考
一、为什么我们需要数据库呢?
就是我想问大家一个问题,就是我们为什么会需要数据库来存储数据呢,我们如果想存储数据可以用其他方法呀,比如用一个文本就可以存储呀,又何必谈何用到数据库呢?
数据库的相关特点:
持久化存储:数据长期保存,不会因为程序结束而丢失
结构化组织:数据按照特定的数据模型组织
共享性:可以被多个用户和应用共享使用
减少冗余:通过数据共享减少数据重复存储
数据独立性:数据与应用程序相互独立
完整性保障:保证数据的正确性和一致性
安全性控制:提供数据保护机制
我们先了解这些特点,然后我们再结合具体:
我们就以这个学生成绩管理系统来举例:
假设我们用文本文件来存储:
students.txt
2021001,张三,计算机2101班
2021002,李四,计算机2101班
2021003,王五,计算机2102班
scores.txt
2021001,CS101,85,78,82,2023-2024-1
2021001,CS102,88,85,90,2023-2024-1
2021002,CS101,90,88,92,2023-2024-1
文件存储面临的问题:
数据冗余的问题:
# 如果每个学生有多门课程,学生信息重复存储
2021001,张三,计算机2101班,CS101,85,78,82
2021001,张三,计算机2101班,CS102,88,85,90
2021001,张三,计算机2101班,CS103,76,80,85
# 同样的学生信息重复了3次!
数据不一致的问题:
# 如果学生转班,需要修改所有相关记录
# 容易漏改,导致数据不一致
2021001,张三,计算机2101班,CS101,85,78,82 # 已更新
2021001,张三,计算机2101班,CS102,88,85,90 # 漏改了!
2021001,张三,计算机2102班,CS103,76,80,85 # 已更新
复杂查询困难:
java
// 如果要查询"计算机2101班Java程序设计课程平均分"
// 文件操作代码会非常复杂
public double calculateClassAverage(String className, String courseName) {
try {
// 1. 先读取所有学生文件,找到指定班级的学生
List<String> studentsInClass = new ArrayList<>();
BufferedReader studentReader = new BufferedReader(new FileReader("students.txt"));
String line;
while ((line = studentReader.readLine()) != null) {
String[] parts = line.split(",");
if (parts[2].equals(className)) {
studentsInClass.add(parts[0]); // 学号
}
}
// 2. 再读取成绩文件,统计平均分
double total = 0;
int count = 0;
BufferedReader scoreReader = new BufferedReader(new FileReader("scores.txt"));
while ((line = scoreReader.readLine()) != null) {
String[] parts = line.split(",");
String studentId = parts[0];
String course = parts[1];
if (studentsInClass.contains(studentId) && course.equals(courseName)) {
total += Double.parseDouble(parts[5]); // 总评成绩
count++;
}
}
return count > 0 ? total / count : 0;
} catch (IOException e) {
e.printStackTrace();
return 0;
}
}
数据库的优势体现:
相同的查询,数据库体现;
sql
-- 一句SQL完成复杂查询
SELECT AVG(s.total_score) as 平均分
FROM scores s
JOIN students st ON s.student_id = st.id
JOIN courses c ON s.course_id = c.id
JOIN classes cl ON st.class_id = cl.id
WHERE cl.class_name = '计算机2101班'
AND c.name = 'Java程序设计';
二、数据库解决的核心问题:
1.数据一致性:
c
-- 学生转班,只需更新一次
UPDATE students SET class_id = 2 WHERE id = 1;
-- 所有相关查询自动获取最新数据,不会出现不一致
2.并发控制:
c
// 多个老师同时录入成绩,文件系统会冲突
// 数据库自动处理并发
public class ScoreService {
public synchronized boolean saveScore(Score score) {
// 数据库事务保证数据完整性
Connection conn = null;
try {
conn = DBUtil.getConnection();
conn.setAutoCommit(false);
// 检查是否已存在记录
String checkSql = "SELECT id FROM scores WHERE student_id = ? AND course_id = ?";
PreparedStatement checkStmt = conn.prepareStatement(checkSql);
checkStmt.setInt(1, score.getStudentId());
checkStmt.setInt(2, score.getCourseId());
ResultSet rs = checkStmt.executeQuery();
if (rs.next()) {
// 更新 existing record
updateScore(conn, score);
} else {
// 插入 new record
insertScore(conn, score);
}
conn.commit();
return true;
} catch (SQLException e) {
if (conn != null) {
try { conn.rollback(); } catch (SQLException ex) {}
}
return false;
}
}
}
3.复杂查询和统计:
sql
-- 成绩分布统计
SELECT
CASE
WHEN total_score >= 90 THEN '优秀'
WHEN total_score >= 80 THEN '良好'
WHEN total_score >= 70 THEN '中等'
WHEN total_score >= 60 THEN '及格'
ELSE '不及格'
END as 等级,
COUNT(*) as 人数,
ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM scores WHERE course_id = 1), 2) as 百分比
FROM scores
WHERE course_id = 1
GROUP BY
CASE
WHEN total_score >= 90 THEN '优秀'
WHEN total_score >= 80 THEN '良好'
WHEN total_score >= 70 THEN '中等'
WHEN total_score >= 60 THEN '及格'
ELSE '不及格'
END
ORDER BY MIN(total_score) DESC;
4.数据完整性约束:
sql
-- 数据库自动强制执行业务规则
ALTER TABLE scores
ADD CONSTRAINT chk_score_range
CHECK (regular_score >= 0 AND regular_score <= 100);
ALTER TABLE scores
ADD CONSTRAINT chk_final_score
CHECK (final_score >= 0 AND final_score <= 100);
-- 防止重复成绩记录
ALTER TABLE scores
ADD UNIQUE unique_student_course (student_id, course_id, semester);
5.具体场景对比:
文件查询:
java
public void getCourseScores(String teacherId, String courseId) {
// 1. 读取课程文件,找到课程
// 2. 读取教师授课关系文件
// 3. 读取学生选课文件
// 4. 读取成绩文件
// 需要4个文件操作,多次循环匹配
// 代码复杂,性能低下
}
数据库方案:
sql
SELECT s.name as 学生姓名, sc.regular_score as 平时成绩,
sc.final_score as 期末成绩, sc.total_score as 总评成绩
FROM scores sc
JOIN students s ON sc.student_id = s.id
WHERE sc.course_id = ? AND sc.teacher_id = ?
ORDER BY s.student_number;
为什么需要数据库:
对于你的项目来说,数据库是必需的,因为:
-
数据结构复杂
-
多个表之间存在复杂关系(学生-课程-成绩-教师)
-
需要维护数据的一致性和完整性
-
-
查询需求复杂
-
需要多表关联查询
-
需要聚合统计(平均分、最高分、排名等)
-
需要条件组合查询
-
-
并发访问需求
-
多个老师可能同时录入成绩
-
学生同时查询成绩
-
需要事务保证数据安全
-
-
数据量会增长
-
每个学期都会新增大量成绩记录
-
需要高效的查询性能
-
-
业务规则复杂
-
成绩计算公式
-
数据验证规则
-
权限控制需求
-
什么情况下可以用文件?
-
配置信息:系统配置参数
-
日志文件:操作日志记录
-
静态数据:很少变化的参考数据
-
小型个人应用:数据量小,结构简单
结论
对于学生成绩管理系统 这种具有复杂关系、需要高效查询、多人并发访问的企业级应用,数据库是唯一正确的选择。文件存储只适用于极其简单的数据存储需求。
你的项目选择MySQL数据库是完全正确的,这为系统的稳定性、性能和可扩展性奠定了坚实基础!
三、自己的见解:
-
数据写死(硬编码): 关系是静态的、固化的。任何业务逻辑的变更(比如新增一个分类、修改用户归属)都必须修改代码并重新部署。数据与关系缺乏"生命力"和"可管理性"。
-
使用数据库: 将数据本身 和数据之间的关系 都存储下来,变成可以动态增、删、改、查 的对象。这正是"数据库"这个名字的含义------数据的仓库。外键是关系型数据库中定义和强制这种"关系"的核心机制之一。
外键:不仅仅是"表示关系"
您说"用外键表示好实体之间的关系",这很对。但外键的作用不止于"表示",更重要的是强制保持数据的一致性与完整性。
举个例子:用户表(users)和 订单表(orders)。订单属于某个用户。
-
有外键时:
-
在
orders表中有一个user_id字段,并设置为指向users.id的外键。 -
数据库会自动保证: 你无法插入一条
user_id在users表中不存在的订单。这避免了"幽灵订单"。 -
当删除一个用户时,你可以通过外键约束定义级联操作(CASCADE, SET NULL, RESTRICT)。
-
RESTRICT: 如果该用户还有订单,则禁止删除此用户。 -
CASCADE: 删除用户时,自动删除他所有的订单。
-
-
作用: 数据的完整性由数据库底层保证,应用层可以更专注于业务逻辑,出错的可能性更低。
-
-
无外键时(即使在数据库中):
-
你只能通过应用程序逻辑来保证:在创建订单前检查用户是否存在,在删除用户前检查他是否有未处理订单。
-
风险:phenyl 如果应用逻辑有漏洞,或者有多个入口(如后台、API、直接操作数据库)可以操作数据,就很容易产生脏数据(无效的
user_id)。
-
现代开发中的权衡与演进
在实际的中大型Web项目中,关于外键的使用有一些更深入的讨论和实践:
-
优势(必须用):
-
**数据强一致性:** 如上所述,是数据库级别的保证,最可靠。
-
**文档化:** 表结构定义本身就直接说明了关系,一目了然。
-
**简化开发:** 很多ORM框架能利用外键自动建立模型关联,方便查询。
-
-
争议与替代方案(可能不用):
-
**性能考量:** 在高并发写入场景下,外键约束检查会带来额外的开销。在分库分表(水平拆分)时,外键难以实现。
-
耦合与灵活性: 外键将数据关系紧密绑定在数据库层。在微服务架构下,订单服务和用户服务可能拥有独立的数据库。这时无法使用数据库外键,而是通过业务代码 或服务间的API调用 来维护逻辑上的关联,这被称为"应用层外键"。
-
**迁移与扩展:** 修改外键关系(特别是生产环境)可能比较麻烦,需要复杂的DDL操作。
-
因此,现代开发中常见的思路是:
-
单体型应用,强一致性要求高: 强烈推荐使用外键。它能以最小成本避免大量数据错误。
-
微服务架构,大规模分布式系统: 通常在数据库层不用外键,因为数据分散在不同服务的数据库中。一致性通过分布式事务(如Saga模式)、最终一致性和应用逻辑来保证。
-
折中方案: 在数据库中定义外键关系 (用于文档化和开发便利),但不添加外键约束 (
FOREIGN KEYconstraint),将一致性检查的责任交给应用层。但这需要极其严谨的团队纪律。
在绝大多数Web项目起步阶段,使用带有外键的关系型数据库(如MySQL, PostgreSQL)是最优、最专业的选择。
一个生动的比喻:
-
写死的数据 像刻在石碑上的家谱,无法更改。
-
有外键的数据库 像一套严谨的家族档案管理系统,每个人都有一个唯一ID,记录父母子女时必须引用有效的ID,系统会自动防止你给一个不存的人当儿子。
-
无外键的数据库 像一个自由记录的家族笔记本,虽然灵活,但需要记录者自己非常小心,否则很容易把关系写乱。
总结
数据库是现代信息系统的核心基础设施 ,它通过结构化存储 、高效查询 、事务保证 和安全管理 ,为应用程序提供了可靠的数据支撑。掌握数据库技术不仅是完成当前项目的需要,更是成为一名合格软件工程师的必备技能。随着数据量的爆炸式增长,数据库技术的重要性将愈发凸显。