343 lines
11 KiB
Markdown
343 lines
11 KiB
Markdown
# 电子书管理系统
|
||
|
||
## 用户需求分析
|
||
|
||
主要面向对象:我自己
|
||
|
||
数据需求:
|
||
|
||
- 图书信息
|
||
- 统计信息
|
||
- 图书附加信息
|
||
- 主机和存储设备信息
|
||
|
||
功能需求:
|
||
|
||
- 上传并存储电子书,具有不同副本管理的功能,同时需要有历史记录功能
|
||
- 搜索并下载电子书
|
||
- 对电子书的进行分类管理,基本的有按照类别、作者、年份等
|
||
- 书单功能
|
||
- 笔记注释功能
|
||
- 多用户功能和管理员功能
|
||
|
||
## 数据字典分析
|
||
|
||
### 数据处理
|
||
|
||
- 用户管理
|
||
- 处理过程名:用户管理
|
||
- 说明:管理员对用户信息进行基本的CRUD操作
|
||
- 输入:CRUD请求、用户基本信息
|
||
- 输出:D1中的用户信息记录
|
||
- 图书管理
|
||
- 处理过程名:图书管理
|
||
- 说明:用户新建、修改、查询、删除图书数据
|
||
- 输入:请求、用户身份、图书数据
|
||
- 输出:D2图书信息
|
||
- 存储管理
|
||
- 处理过程名:存储管理
|
||
- 说明:从其他处理过程中接收数据和请求,实际操作电子书在服务器上的存放
|
||
- 输入:D2的图书编号、D1的用户身份、存取操作
|
||
- 输出:D3存储信息
|
||
- 上传下载管理
|
||
- 处理过程名:上传下载管理
|
||
- 说明:用户对指定的文档进行上传和下载
|
||
- 输入:电子文档的文件属性数据、用户的操作请求
|
||
- 输出:D5存取记录、存取操作
|
||
- 笔记管理
|
||
- 处理过程名:笔记管理
|
||
- 说明:用户在特定的书籍上添加和查看笔记
|
||
- 输入:用户请求、D1用户身份、D2图书编号
|
||
- 输出:D4中的笔记记录
|
||
- 分类信息维护
|
||
- 处理过程名:分类信息维护
|
||
- 说明:在添加书籍时,维护分类和作者信息,方便统计查询
|
||
- 输入:电子文档的图书数据
|
||
- 输出:D6、D7
|
||
|
||
上传一本书:首先检查用户信息和配额,增加上传记录,如果存在图书,则直接修改存储信息;如果不存在图书,则需要先新建图书,然后再写入存储,同时更新关联表信息。
|
||
|
||
下载一本书:检查用户权限,查询存储信息,更新下载记录
|
||
|
||
删除一本书:检查用户权限;如果是删除副本,直接修改存储信息;如果是删除图书,首先需要删除全部的副本,然后删除图书条目,最后删除关联表信息。
|
||
|
||
新建用户:直接修改用户表
|
||
|
||
删除用户:检查用户名下的图书和存储、书单信息,先执行删除数目的操作,然后再修改用户表
|
||
|
||
添加笔记:先找图书表,然后结合用户,单独写入笔记表
|
||
|
||
删除笔记:先找图书表,然后结合用户,单独修改笔记表
|
||
|
||
### 数据流
|
||
|
||
- 数据流名:管理数据
|
||
|
||
说明:管理员验证身份,建立用户档案
|
||
|
||
来源去向:管理员 -> P1
|
||
|
||
数据结构: 密码+用户信息表
|
||
|
||
- 数据流名:用户身份
|
||
|
||
说明:不同的用户身份进入的处理过程不同。
|
||
|
||
来源去向:P1->P2.1 P1->P2.2
|
||
|
||
数据结构: 用户信息表
|
||
|
||
- 数据流名:查询请求
|
||
|
||
说明:通过书名和类别查询库中的图书
|
||
|
||
来源去向:用户 -> P2.1
|
||
|
||
数据结构: 类别/书名,图书信息表
|
||
|
||
- 数据流名:图书数据
|
||
|
||
说明:根据电子文档对应的图书情况新建图书记录
|
||
|
||
来源去向:图书 -> P2.1,图书 -> P2.3
|
||
|
||
数据结构: 图书信息表
|
||
|
||
- 数据流名:文件数据
|
||
|
||
说明:上传文件时,需要提供文件的属性
|
||
|
||
来源去向:电子文档 -> P3
|
||
|
||
数据结构: 文件属性表
|
||
|
||
- 数据流名:存取情况
|
||
|
||
说明:提供存取操作的数据封装,完成实际的数据存取
|
||
|
||
来源去向:P3 -> P2.2
|
||
|
||
数据结构: 存取操作结构
|
||
|
||
- 数据流名:图书编号
|
||
|
||
说明:通过图书编号来识别和每种图书相关的数据
|
||
|
||
来源去向:P2.1->P4, P2.1->P2.2
|
||
|
||
数据结构: 类别/书名,图书信息表
|
||
|
||
- 数据流名:笔记请求
|
||
|
||
说明:通过图书编号发起添加或者查看笔记的请求。
|
||
|
||
来源去向:用户 -> P4
|
||
|
||
数据结构: 图书编号,笔记信息
|
||
|
||
### 数据存储
|
||
|
||
- 数据存储名:用户信息
|
||
|
||
说明:存放注册用户的相关信息,邮箱需要唯一
|
||
|
||
编号:D1
|
||
|
||
组成:用户编号,用户名,用户邮箱,用户密码,用户空间占用,用户配额,注册日期
|
||
|
||
数据量:不多于10条
|
||
|
||
存取频度:每天100次
|
||
|
||
存取方式:随机检索为主
|
||
|
||
- 数据存储名:图书信息
|
||
|
||
说明:电子书的出版相关的信息,ISBN唯一,不包括实际的电子书文档信息
|
||
|
||
编号:D2
|
||
|
||
组成:编号,ISBN,出版社,类型,作者,日期,语言
|
||
|
||
数据量:500条左右
|
||
|
||
存取频度:每天200次
|
||
|
||
存取方式:随机检索和更新
|
||
|
||
- 数据存储名:存储信息
|
||
|
||
说明:电子书文档的相关数据,和图书信息密切相关
|
||
|
||
编号:D3
|
||
|
||
组成:副本编号,资源URL,大小,日期
|
||
|
||
数据量:800条左右
|
||
|
||
存取频度:每天300次
|
||
|
||
存取方式:随机检索为主
|
||
|
||
- 数据存储名:笔记信息
|
||
|
||
说明:读者对图书发表的笔记和注解
|
||
|
||
编号:D4
|
||
|
||
组成:编号,日期,内容
|
||
|
||
数据量:1600条左右
|
||
|
||
存取频度:每天300次
|
||
|
||
存取方式:随机检索和插入
|
||
|
||
- 数据存储名:存取记录
|
||
|
||
说明:记录电子书文档的上传、下载和删除,方便统计和故障查询
|
||
|
||
编号:D5
|
||
|
||
组成:图书副本编号,用户编号,操作类型,日期
|
||
|
||
数据量:2000条左右
|
||
|
||
存取频度:每天300次
|
||
|
||
存取方式:主要是按照时间顺序插入,有时会有全表统计查询
|
||
|
||
- 数据存储名:类型信息
|
||
|
||
说明:记录图书的类型,方便统计和查询
|
||
|
||
编号:D6
|
||
|
||
组成:类型编号,类型名称
|
||
|
||
数据量:200条左右
|
||
|
||
存取频度:每天100次
|
||
|
||
存取方式:随机CRUD
|
||
|
||
- 数据存储名:作者信息
|
||
|
||
说明:记录图书的作者,方便统计和查询
|
||
|
||
编号:D7
|
||
|
||
组成:作者编号,作者姓名
|
||
|
||
数据量:200条左右
|
||
|
||
存取频度:每天100次
|
||
|
||
存取方式:随机CRUD
|
||
|
||
## 概念结构设计
|
||
|
||
### 实体分析
|
||
|
||
实体:管理员、用户、图书、文件、笔记、类型、作者
|
||
|
||
语义描述:
|
||
|
||
1. 一个系统里面有多个相互独立的用户,用户拥有多个图书,图书可以对应多个版本的文件,图书可以有多个笔记。一个文件只能对应一本图书。
|
||
2. 系统只有一个管理员,管理员不是用户,只有操作用户账户的权限,不具有对其他信息进行操作的权限。
|
||
3. 一个用户只能管理自己所拥有的图书、文件和笔记
|
||
4. 用户有存储空间配额的限制,上传的文件不能超过配额。
|
||
5. 一本图书可以被分到多个类别里面,一个类里面有多本书;一本书可以有多个作者,一个作者可以写多本书
|
||
|
||
### E-R图
|
||
|
||
占位符
|
||
|
||
## 逻辑结构设计
|
||
|
||
### 转换关系
|
||
|
||
实体转换:
|
||
- 管理员:admin(密码)
|
||
- 系统中只有一个管理员,密码只能通过直接操作数据库修改,这仅作为一个存储项,也不需要主键之类的东西。
|
||
- 用户:user(<u>用户ID</u>, 用户名, 用户邮箱, 用户密码, 用户配额, 注册日期)
|
||
|
||
- 图书:book(<u>图书ID</u>,ISBN,出版社,日期,语言,标题)
|
||
|
||
- 文件:document(<u>文件ID</u>,资源URL,大小,日期,类型,副本名)
|
||
|
||
- 笔记:note(<u>笔记ID</u>,日期,内容,标题)
|
||
|
||
- 类型:type(<u>类型ID</u>, 类型名称)
|
||
|
||
- 作者:author(<u>作者ID</u>, 作者姓名)
|
||
|
||
联系转换:
|
||
|
||
- 管理:管理不直接通过数据表体现,因此不需要添加任何的关系。
|
||
- 拥有:一对多关系,因此在图书里面添加外键用户ID,修改图书关系为book(<u>图书ID</u>,用户ID(**FK ref user**),ISBN,出版社,日期,语言, 标题)
|
||
- 存取:一对多关系,但是由于该联系有自己的属性,所有单独新建一个关系 record(<u>记录ID</u>,时间,操作类型,用户ID,文件URL)。由于这里可能涉及到删除操作,因此使用外键,仅保留存取记录。
|
||
- 对应:一对多关系,直接在文件里面添加外键图书ID,修改文件关系为document(<u>文件ID</u>,图书ID(**FK ref book**),资源URL,大小,日期)
|
||
- 图书-笔记:一对多关系,直接在笔记关系中增加外键,修改关系为note(<u>笔记ID</u>,图书ID(**FK ref book**),日期,内容)
|
||
- 图书-作者:多对多关系,单独建立一个关系book_author(<u>图书ID(**FK ref book**),作者ID(**FK ref author**)</u>)
|
||
- 图书-类型:多对多关系,单独建立一个关系book_type(<u>图书ID(**FK ref book**),类型ID(**FK ref type**)</u>)
|
||
|
||
### 关系模式优化
|
||
|
||
#### 函数依赖集和范式
|
||
|
||
book_author、book_type两个为全码,无非主属性,必然满足BCNF
|
||
|
||
其余关系的函数依赖集如下:
|
||
|
||
- type:`{类型ID->类型名称}`
|
||
- author:`{作者ID->作者姓名}`
|
||
- user:`{用户ID->用户名, 用户ID->用户邮箱, 用户ID->用户密码, 用户ID->用户配额, 用户ID->注册日期}`
|
||
- book:`{图书ID->用户ID, 图书ID->ISBN, 图书ID->出版社, 图书ID->日期, 图书ID->语言, 图书ID->标题}`
|
||
- document:`{文件ID->图书ID, 文件ID->资源URL, 文件ID->大小, 文件ID->日期}`
|
||
- note:`{笔记ID->图书ID, 笔记ID->日期, 笔记ID->内容, 笔记ID->标题}`
|
||
- record:`{记录ID->用户ID, 记录ID->操作类型, 记录ID->时间, 记录ID->文件URL}`
|
||
|
||
可以看出,他们均为非主属性对码的完全函数依赖,满足BCNF。
|
||
|
||
#### 其他优化
|
||
|
||
冗余设计:
|
||
|
||
- 因为用户可能会经常需要看自己发布的笔记,虽然可以通过先查book表再查note,但是这样会降低查询效率,因此在note关系中添加用户ID。对于document也需要做同样的冗余属性列的添加,以提高某些情况下的查询效率。
|
||
- 建立一个用户的统计数据表,里面存放了用户占用的存储空间、创建的图书数量、种类等信息,可以减少查询时的数据库压力。
|
||
|
||
简化属性:
|
||
|
||
- 由于时间戳是唯一的,因此在record这种不需要更新的表中,可以用时间戳来代替ID作为主键。
|
||
|
||
安全性设计:
|
||
|
||
- 数据加密:用户的密码通过加盐md5的方式存储在数据库中
|
||
- SQL注入预防,交给框架来完成
|
||
|
||
完整性约束:
|
||
|
||
- 实体完整性:各个关系的主键
|
||
- 参照完整性:。。。表中的外键
|
||
- 自定义完整性:用户占用的存储空间不能超过配额,也就是用户的文件关系中,文件大小属性之和不能大于用户的配额。
|
||
|
||
触发器:
|
||
|
||
- 对于book表、document表、author表和type表,在更改时自动更新统计信息表
|
||
|
||
## 物理结构设计
|
||
|
||
### 存储结构
|
||
|
||
- 存放位置为本地
|
||
- 存储结构为单机关系型数据库
|
||
|
||
### 数据存取
|
||
|
||
- 对于type、author、user这三个表而言,一般只需要通过ID查询,因此无需建立额外的索引优化,直接用主键索引即可。book_author、book_type这两个全码表更是如此。
|
||
- 对于book、document、note、record有对于非主属性的联合和范围查询的需求,主要是对日期的范围查询,对于类型、作者等属性的联合查询。其中,对于范围较小的属性,如图书的语言、出版社、类型等属性,可以不建立索引。对于标题、日期等范围较大的索引,根据启发式规则建立相应的索引。
|
||
|
||
## 最终的表设计
|
||
|