# 电子书管理系统 ## 用户需求分析 主要面向对象:我自己 > 数据需求: > - 图书信息 - 统计信息 - 图书附加信息 - 主机和存储设备信息 功能需求: - 上传并存储电子书,具有不同副本管理的功能,同时需要有历史记录功能 - 搜索并下载电子书 - 对电子书的进行分类管理,基本的有按照类别、作者、年份等 - 书单功能 - 笔记注释功能 - 多用户功能和管理员功能 ## 数据字典分析 ### 数据处理 - 用户管理 - 处理过程名:用户管理 - 说明:管理员对用户信息进行基本的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(用户ID, 用户名, 用户邮箱, 用户密码, 用户配额, 注册日期) - 图书:book(图书ID,ISBN,出版社,日期,语言,标题) - 文件:document(文件ID,资源URL,大小,日期,类型,副本名) - 笔记:note(笔记ID,日期,内容,标题) - 类型:type(类型ID, 类型名称) - 作者:author(作者ID, 作者姓名) 联系转换: - 管理:管理不直接通过数据表体现,因此不需要添加任何的关系。 - 拥有:一对多关系,因此在图书里面添加外键用户ID,修改图书关系为book(图书ID,用户ID(**FK ref user**),ISBN,出版社,日期,语言, 标题) - 存取:一对多关系,但是由于该联系有自己的属性,所有单独新建一个关系 record(记录ID,时间,操作类型,用户ID,文件URL)。由于这里可能涉及到删除操作,因此使用外键,仅保留存取记录。 - 对应:一对多关系,直接在文件里面添加外键图书ID,修改文件关系为document(文件ID,图书ID(**FK ref book**),资源URL,大小,日期) - 图书-笔记:一对多关系,直接在笔记关系中增加外键,修改关系为note(笔记ID,图书ID(**FK ref book**),日期,内容) - 图书-作者:多对多关系,单独建立一个关系book_author(图书ID(**FK ref book**),作者ID(**FK ref author**)) - 图书-类型:多对多关系,单独建立一个关系book_type(图书ID(**FK ref book**),类型ID(**FK ref type**)) ### 关系模式优化 #### 函数依赖集和范式 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有对于非主属性的联合和范围查询的需求,主要是对日期的范围查询,对于类型、作者等属性的联合查询。其中,对于范围较小的属性,如图书的语言、出版社、类型等属性,可以不建立索引。对于标题、日期等范围较大的索引,根据启发式规则建立相应的索引。 ## 最终的表设计