由于本文格式原来是word,所以文中有些格式不太对。如果这篇文章对你有帮助,麻烦点赞评论一下谢谢!源码和word文档可私聊领取~

目录

  • 一、相关技术介绍
    • 1.1 RDBMS:
    • 1.2应用程序开发环境:
    • 1.3系统开发环境:win10
    • 1.4 系统生产环境:
    • 1.5 简单介绍
      • 1.5.1 API文档
      • 1.5.2 项目维护记录
  • 二、需求分析
    • 2.1需求分析:
    • 2.2信息需求:
    • 2.3处理需求:
    • 2.4安全性和完整性需求:
    • 2.5功能需求:
    • 2.6数据字典:
    • 2.7数据结构:
    • 3.1概念模型:E-R图;
    • 3.2应用程序的模块层次结构图:
    • 3.3关系模型图:
    • 4.1 E-R图向关系模型的转换;
      • 4.1.1 数据库模式
    • 4.2用户子模式(所有视图的定义);
    • 4.3安全性(用户类别和权限)设计和实现说明;
    • 4.4完整性(主、外码和用户自定义的完整性约束)设计和实现说明
      • 4.4.1 主外码结构
      • 4.4.2 用户自定义的完整性
    • 4.5存储过程
    • 4.6触发器
      • 4.6.1 定义的第一种触发器
      • 4.6.2 定义的第二种触发器
  • 五、数据库物理设计
    • 5.1所有索引的定义;
    • 5.2数据的存放位置说明;
    • 5.3系统配置说明;
      • 5.3.1网络方面的配置,修改/et/sysctl.conf文件
      • 5.3.2.打开文件数的限制
    • 5.4模块设计(模块IPO图)
    • 5.5 表结构;(钥匙代表主键)
  • 六、功能模块设计
    • 6.1 左外连接、嵌套组合、分组查询
    • 6.2 字符串匹配、模糊、多表连接查询
    • 6.3 多表连接、字符串匹配、模糊、聚集函数查询
    • 6.4 limit实现的分页查询
    • 6.5 事务查询的实现
  • 七、数据库实施
    • 7.1数据库及数据库对象的SQL脚本文件:建表语句在附录(报告最后面)
    • 7.2数据库备份和恢复方案
      • 7.21备份策略的设计思路
    • 7.3数据库备份和恢复实践
    • 7.4日志基本操作
  • 八、系统运行与维护
    • 8.1 界面展示
      • 8.1.1登录界面
      • 8.1.2首页
      • 8.1.3页面展示界面
      • 8.1.4数据统计界面
    • 8.2系统代表性的功能
      • 8.2.1雪花算法用户主键
      • 8.2.2 数据加密存储
      • 8.2.3 接口加密传输
      • 8.2.3 并发问题的初步解决
      • 8.2.4 非关系型数据库Redis的使用
      • 8.2.5 Java Web Token的使用
      • 8.2.6 生产环境部署上线
  • 九、总结
    • 收获与体会
    • 系统需要改进的地方
  • 十、附录
    • 10.1建表语句
      • 10.1.1 cashier表
      • 10.1.2 commodidy表
      • 10.1.3 department表
      • 10.1.4role表
      • 10.1.5 sales表
      • 10.1.6 staff表
      • 10.1.7 supplier表
      • 10.1.8 supply表
      • 10.1.9 user表
      • 10.1.10 warehouse表
    • 10.2建视图语句
      • 10.2.1 一月商品销量视图
      • 10.2.2 上半年商品销量视图

一、相关技术介绍

对使用的RDBMS、应用程序开发环境、系统运行环境、开发工具及版本作简单的介绍。

1.1 RDBMS:

Mysql 5.7.32,Redis 2.8.9(缓存中间件)

1.2应用程序开发环境:

JDK1.8,J2EE

1.3系统开发环境:win10

B/S结构:

后端:springboot+mysql+springcloud+mybatisplus

前端:nodejs + NUXT + elementUI + vue

运维:docker

版本控制:git

1.4 系统生产环境:

Linux CentOS 7.3
(项目部署在阿里云服务器,域名是http://39.108.136.207/#/login)

安全组规则,防火墙端口开放

1.5 简单介绍

1.5.1 API文档

接口信息在启动前后端服务器后访问http://localhost:9004/swagger-ui.html#/

1.5.2 项目维护记录

项目维护的所以记录都放在了gitee码云的远程仓库

前端项目:https://gitee.com/fang-jiale/vue_management_system

后端项目:https://gitee.com/fang-jiale/supermarket_management_system

前端项目的分支,分别是开发对应模块建立出来的。后端只有master分支。

二、需求分析

2.1需求分析:

本次课设,需要完成一个超市管理系统,能够进行增删改查的基本操作,用户在前端网页发送请求时,前端将用户的数据发送到后端,然后查询数据库后响应回去。该系统让用户清楚直观地看到超市内部列表的数据,有权限的用户可以对其进行增删改查功能。

2.2信息需求:

1、用户信息:

用户编号、用户名、密码、真实姓名、性别、出生年月、手机号、注册日期。

2、商品信息:

商品编号、商品名、促销开始时间、促销结束时间、相册描述、促销价格、库存。

3、购买清单信息:

订单编号、收银台编号、商品编号、购买数量、购买日期、用户编号。

4、供应关系信息:

商品编号、供应商编号、供应数量、供应价格、供应日期

5、角色信息:

角色编号、角色名。

  1. 职员信息:

职员编号、职员名、职员性别、职员年龄、职员职位、薪水、部门编号、收银台编号

  1. 数据统计信息:

    上半年每月销量、商品名称

8、部门信息、供应商信息、收银台信息、仓库信息

2.3处理需求:

1、公共区域

该系统共有四个角色,普通用户,超市员工,超市管理员,DBA都可以看到商品列表和用户列表。但是普通用户只能看商品列表和用户列表,超市员工和超市管理员都可以看除权限管理外的列表,但是员工只有部分增删改权限,DBA拥有全部权限。

2、登录

用户可以通过登录页面登录。

登录时用户必须要填写用户名、密码,通过验证后方可进入对应的界面。

  1. 增删改操作

由第一点可知,用户根据自己响应的角色只能对自己能够访问的界面的数据进行增删改的操作。

  1. 数据统计信息

    所有用户都可以访问数据统计信息,看到商品销量。

2.4安全性和完整性需求:

1、所有用户均可搜索、访问用户列表和商品列表,超市员工和超市管理员都可以看除权限管理外的列表,但是员工只有部分增删改权限,DBA拥有全部权限。

2、超市员工只可查看后台管理模块所有列表的信息,但是不能修改,超市管理员和DBA可修改信息。

3、每个用户由用户用户编号唯一标识,用户编号由雪花算法生成;用户名不能与其他用户相同,长度是3到10位;用户的密码不允许为空,长度在3到15位;系统自动记录创建时间;

4、超市职员的出生年月在合理范围,且拥有唯一编号;年龄范围在18-66岁之间;

5、每个商品拥有唯一标识;

6、购买清单中的每条元组都有唯一的oid;系统自动记录创建时间;

2.5功能需求:



该程序主要功能需求如下:

  1. 用户登录:采用用户名及密码验证模式,进入管理系统前,用户必须在登陆页面输入用户名及密码,只有验证通过的用户方可进入超市管理系统操作主页面。

  2. 用户管理:包括一个功能模块:对学生信息进行增删改查,对用户可用状态的禁用。

  3. 商品管理:包括两个功能模块:商品清单、购买清单,实现了简单的增删改查功能。

  4. 后台管理:包括四个功能模块:员工列表、部门列表、供应商列表、供应关系列表,实现了简单的增删改查功能。

  5. 数据统计:通过查询数据库封装好的表和视图,直观的显示各个商品上半年来的销量趋势变化。

  6. 权限管理:通过前后端控制,对拥有权限的用户才展示数据。

2.6数据字典:

  1. 商品清单:commodity
字段名 中文字段名 字段类型 长度 主键/外键 字段值约束
cid 商品编号 char 13 P NOT NULL
cname 名称 char 10 NOT NULL
price 基础售价 int 10 NOT NULL
promotion_start 促销开始日期 date
promotion_end 促销结束日期 date
discount_price 折扣价 int 10
stock 库存 int 10 NOT NULL
on_sale 是否可售 smallint 2 NOT NULL
wid 仓库号 char 10 F NOT NULL
  1. 部门清单department
字段名 中文字段名 字段类型 长度 主键/外键 字段值约束
did 部门编号 char 13 P NOT NULL
dname 部门名称 char 10 NOT NULL
population 人数 char 10 NOT NULL
director 主管 char 13 F NOT NULL

主管也是员工,是员工编号的外键

  1. 员工清单staff
字段名 中文字段名 字段类型 长度 主键/外键 字段值约束
sid 员工号 char 13 P NOT NULL
sname 姓名 char 10 NOT NULL
ssex 性别 char 2 NOT NULL
sage 年龄 smallint 2 NOT NULL
position 职称 char 10 NOT NULL
salary 工资 char 10 NOT NULL
did 部门号 char 13 F NOT NULL
cashier_id 收银台号 char 13 F
  1. 用户清单user
字段名 中文字段名 字段类型 长度 主键/外键 字段值约束
id 用户编号 char 30 P NOT NULL
username 用户名 char 20 NOT NULL
password 密码 varchar 200 NOT NULL
mobile 手机号 char 11 NOT NULL
realname 真实姓名 char 10 NOT NULL
accumulated_co nsumption_amount 累计消费金额 int 10 NOT NULL
create_time 创建时间 timestamp NOT NULL
data_status 禁用状态 smallint 2 NOT NULL
last-ip 上次登录ip varchar 16
Version 乐观锁 int 10
rid 角色编号 Smallint 6 F NOT NULL
  1. 供应清单supply
字段名 中文字段名 字段类型 长度 主键/外键 字段值约束
cid 商品编号 char 13 P/F NOT NULL
supplier_id 供应商编号 char 10 P/F NOT NULL
number 数量 int 10 NOT NULL
supply_price 供应单价 char 10 NOT NULL
date 供应日期 datetime NOT NULL
  1. 购买清单sales
字段名 中文字段名 字段类型 长度 主键/外键 字段值约束
oid 订单编号 char 20 P NOT NULL
cashier_id 收银台编号 char 10 F NOT NULL
cid 商品编号 char 13 F NOT NULL
number 数量 int 10 NOT NULL
date 购买日期 datetime NOT NULL
uid 用户编号 int 13 F NOT NULL

用户会重复买某一商品,在不同日期,所以不是主键

  1. 供应商清单supplier
字段名 中文字段名 字段类型 长度 主键/外键 字段值约束
supplier_id 供应商编号 char 10 P NOT NULL
supplier 供应商名称 char 20 NOT NULL
mobile 电话 char 11 NOT NULL
sid 员工编号 char 13 F NOT NULL

一个员工对应多个供应商,一个供应商只对应一个员工。

  1. 收银台清单cashier
字段名 中文字段名 字段类型 长度 主键/外键 字段值约束
cashier_id 收银台号 char 10 P NOT NULL
start_time 每天开始工作时间 datetime NOT NULL
end_time 每天结束工作时间 datetime NOT NULL
cashier_ ammount 台内账户金额 int 10 NOT NULL
  1. 仓库清单warehouse
字段名 中文字段名 字段类型 长度 主键/外键 字段值约束
wid 仓库编号 char 10 P NOT NULL
address 地址 char 20 NOT NULL
sid 员工编号 char 13 F NOT NULL
  1. 角色列表role
字段名 中文字段名 字段类型 长度 主键/外键 字段值约束
rid 角色编号 smallint 6 P NOT NULL
role_name 角色名 char 10 NOT NULL

2.7数据结构:

名称 别名 含义 组成
用户信息 User表 用户的基本信息 用户编号+用户名+真实姓名+密码+ 累计消费金额+手机号+禁用状态+注册日期+乐观锁版本号+角色号
商品信息 Commodity表 商品的基本信息 商品编号+商品名+价格+促销开始时间+促销结束时间+促销价+库存+可售状态+仓库号
购买清单信息 Sales表 购买清单的基本信息 订单编号+收银台编号+商品编号+ 购买数量+订单创建时间+购买用户的编号
仓库信息 Warehouse表 仓库基本信息 仓库号+仓库地址+管理仓库的员工编号
供应关系信息 Supply表 供应关系信息 商品编号+供应商编号+供应商品数量+供应价格+供应日期
供应商信息 Supplier表 供应商信息 供应商编号+供应商名称+手机号+管理供应商的员工

三、概念结构设计

3.1概念模型:E-R图;

3.2应用程序的模块层次结构图:

H图:

3.3关系模型图:

四、逻辑结构设计

4.1 E-R图向关系模型的转换;

4.1.1 数据库模式

商品清单(商品编号、名称、基础售价、促销开始日期、促销结束日期、折扣价、库存、是否可售、仓库号)满足第三范式

部门清单(部门编号、部门名称、人数、主管)满足第三范式

员工清单(员工号、姓名、性别、年龄、职称、工资、部门号、收银台号),满足第三范式

用户清单(用户编号,用户名,密码,手机号,真实姓名,累计消费金额,创建时间,禁用状态,上次登录ip,乐观锁版本,角色编号)满足第三范式

供应清单(商品编号,供应商编号,数量,供应单价)满足第三范式

购买清单(订单编号,收银台编号,商品编号,数量,购买日期,用户编号)满足第三范式

供应商清单(供应商编号,供应商名称,电话,员工编号)满足第三范式

收银台清单(收银台号,每天开始工作时间,每天结束时间,台内账户金额)满足第三范式

仓库清单(仓库编号,地址,员工编号)满足第三范式

角色清单(角色编号,角色名)满足第三范式

4.1.2 数据库外模式

1、商品上半年每月销量视图(商品编号, 商品名称, 月销量)

2、商品上半年销量视图(商品编号, 商品名称, 月销量)

4.2用户子模式(所有视图的定义);



(一月销量)
(半年销量)

定义了各类商品上半年每月销量的视图,还有上半年商品1-6月销量的视图

一月销量视图的查询(其余五月类似):

CREATE VIEW january AS

SELECT DISTINCT s.cid ,c.cname, IFNULL(january,0) january

FROM commodity c,sales s LEFT OUTER JOIN

(SELECT s.cid, c.cname, SUM(number) january

FROM sales s, commodity c

where date BETWEEN ‘2021-01-01’ AND ‘2021-01-31’ AND s.cid = c.cid

GROUP BY s.cid) j ON (s.cid=j.cid)

where c.cid=s.cid

采用左外连接查询和嵌套查询,因为要考虑到即使商品在当月没有销量,也要展示出其的商品名。视图都是建立在基本表上的,所以当购买清单产生或是更改时,视图也会随之更改,可以减少维护。

4.3安全性(用户类别和权限)设计和实现说明;

总共分为四种用户

第一种:root用户,拥有对数据库操作的所有权限,给予DBA使用。

第二种:supermarket-staff,给超市普通职工人员使用,拥有对数据库所有表的查询权限,只对商品和用户的购买清单内的元组有增删改查的功能,对表没有操作权限。

第三种:supermarket-admin,给超市的管理人员使用,拥有对数据库所有表内元组的增删改查权限,**对表没有操作权限(无法增删表等)。**此外,拥有创建视图展示视图的权限。

第四种:user,只有对商品的查询功能和用户列表以及查询数据报表视图的查询功能。



分布对应着角色表的这四个角色。

4.4完整性(主、外码和用户自定义的完整性约束)设计和实现说明

4.4.1 主外码结构

主外码结构如图

主外键建立规则:由ER图易知,实体关系1对多的,外键建立在多的一方,实体关系多对多的,外键建立在中间表里。而主键和外键在上文的数据字典中清楚标识,在此简略书写。外键在更新和删除时的操作都是默认RESTRICT

表名 主键 外键
cashier cashier_id
commodity cid wid:参照warehouse的wid,仓库号
department did director:参照staff的sid,主管也是员工
sales oid cid:参照commodity的cid 商品编号 2. id: 参考user的id 用户编号
staff sid cashier_id 参照cashier的cashier_id 收银台号 did 参照department的did 部门号
supplier supplier_id sid: 参照staff的sid, 员工号,代表一个供应商由一个员工负责
supply cid, supplier_id cid:参照commodity的cid 商品编号 supplier_id:参照supplier的supplier_id
user id Rid: 参照role的角色号
warehouse wid sid: 参照staff的sid 员工号,员工管理仓库
role rid

4.4.2 用户自定义的完整性

1.定义了非空约束:在上文数据字典中可清楚看到

2.默认值约束:user的version(乐观锁版本号)默认为1,user的data_status(禁用状态),其余所有int类型的数据都默认为0。

3.唯一约束:department的部门名dname,user的用户名username,user的手机号mobile

4.5存储过程

测试并尝试使用了存储过程进行对数据库的操作(插入操作)

4.6触发器

4.6.1 定义的第一种触发器

在用户购买商品后,购买清单sales会增加一条元组,元组包含顾客购买商品的数量,由于有更新操作,所以此时相应的从用户表user中增加用户的累计消费金额,并从commodity商品表中减少对应商品的库存,再然后增加收银台的累计消费金额。考虑到涉及多表更新操作,可以使用触发器。

BEGIN

UPDATE commodity as c SET c.stock =c.stock-(new.number) WHERE c.cid= new.cid
;

UPDATE commodity c,user as u SET u.accumulated_consumption_ammount
=u.accumulated_consumption_ammount + (new.number) * c.price WHERE c.cid=
new.cid AND u.id=new.id;

UPDATE commodity c, cashier as cs SET cs.cashier_ammount =cs.cashier_ammount
+(new.number)* c.price WHERE c.cid= new.cid AND cs.cashier_id=new.cashier_id
;

END

删除时同理。

4.6.2 定义的第二种触发器

在插入职员staff数据时,由于数据中包含职员年龄,应该给其限制范围在18至66岁之间,然而低版本的mysql不支持check约束,所以由触发器实现。

CREATE TRIGGER `insert_sage` BEFORE INSERT ON `staff` FOR EACH ROW begin

if(NEW.Sage<66 AND NEW.Sage >= 18) THEN

SET@choice=1;

ELSE

SET@choice=0;

INSERT INTO staff VALUES(1);

end if;

end;

CREATE TRIGGER `update_sage` BEFORE UPDATE ON `staff` FOR EACH ROW begin

if(NEW.Sage<66 AND NEW.Sage >= 18) THEN

SET@choice=1;

ELSE

SET@choice=0;

INSERT INTO `staff` VALUES(1);

end if;

end;

五、数据库物理设计

5.1所有索引的定义;

使用的存取方法时索引方法中的B+树索引存取方法,按照顺序存储数据,B-TREE会将相关的列值都存储在一起,所以有些查询只使用索引就能完成全部查询,共有三个优点:

  1. 索引大大减少了服务器需要扫描的数据量。

  2. 索引可帮助服务器避免排序和临时表。

  3. 索引可以将随机I/O变为顺序I/O。


所有外键都建立了normal索引,还有部分属性建立了唯一索引

5.2数据的存放位置说明;

由于不同PC机所安装的数据库软件不一定相同,所以数据文件与日志文件的存放位置也不一定相同。

本机存储位置如上

MySQL的每个数据库都对应存放在一个与数据库同名的文件夹中,MySQL数据库文件包括MySQL所建数据库文件和MySQL所用存储引擎创建的数据库文件。

MySQL创建并管理的数据库文件:

.frm文件:存储数据表的框架结构,MySQL数据库文件名与表名相同,每个表对应一个同名frm文件,与操作系统和存储引擎无关,即不管MySQL运行在何种操作系统上,使用何种存储引擎,都有这个文件。

除了必有的.frm文件,根据MySQL所使用的存储引擎的不同(MySQL常用的两个存储引擎是MyISAM和InnoDB),存储引擎会创建各自不同的数据库文件。

MyISAM数据库表文件:

.MYD文件:即MY Data,表数据文件

.MYI文件:即MY Index,索引文件

.log文件:日志文件

5.3系统配置说明;

数据库基于操作系统的,目前大多数MySQL都是安装在Linux系统之上,所以对于操作系统的一些参数配置也会影响到MySQL的性能,下面就列出一些常见的系统配置。由于该项目也部署在了阿里云服务器上(Linux系统
CentOS 7.3),所以配置了以下规则。

5.3.1网络方面的配置,修改/et/sysctl.conf文件

#增加tcp支持的队列数 net.ipv4.tcp_max_syn_backlog = 65535
#减少断开连接时,资源回收 net.ipv4.tcp_max_tw_buckets = 8000
net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_fin_timeout =
10

5.3.2.打开文件数的限制

可以使用ulimit
-a查看目录的限制,可以修改/etc/security/limits.conf文件,增加以下内容以修改打开文件数量的限制

* soft nofile 65535* hard nofile 65535

5.4模块设计(模块IPO图)

5.5 表结构;(钥匙代表主键)

commodity商品表

收银台cashier表

Warehouse 仓库表

User 用户列表

Supply供应关系列表

Supplier 供应商列表

Staff 职员列表

Sales购买清单

Department部门表

Role角色列表

六、功能模块设计

基本的增删改查功能已经完成,在此展示较为复杂的查询功能。

6.1 左外连接、嵌套组合、分组查询

CREATE VIEW january AS

SELECT DISTINCT s.cid ,c.cname, IFNULL(january,0) january

FROM commodity c,sales s LEFT OUTER JOIN

(SELECT s.cid, c.cname, SUM(number) january

FROM sales s, commodity c

where date BETWEEN ‘2021-01-01’ AND ‘2021-01-31’ AND s.cid = c.cid

GROUP BY s.cid) j ON (s.cid=j.cid)

where c.cid=s.cid where c.cid=s.cid

建立所有一月份销量视图的时候,要考虑商品在一月份没有销量也要列出的情况,所以要用左外连接查询把销量为空的商品名也列出来,此外要先查出处于一月时间段的订单,再做连接,所以要使用嵌套查询。

6.2 字符串匹配、模糊、多表连接查询

SELECT c.cname, sl.supplier, s.number, s.date, s.supply_price
FROM commodity c, supplier sl, supply s +
WHERE c.cid = s.cid AND s.supplier_id = sl.supplier_id AND sl.supplier LIKE
'%${queryString}%'

当用户在前端发起请求时(按照供应商名称查询供应列表,queryString封装着供应商名称),因为是模糊查询,所以要用%连接字符串,表示任意长度。

6.3 多表连接、字符串匹配、模糊、聚集函数查询


SELECT count(*)
FROM commodity c, supplier sl, supply s
WHERE c.cid = s.cid AND s.supplier_id = sl.supplier_id AND sl.supplier LIKE
'%${queryString}%'

6.4 limit实现的分页查询

SELECT
id,username,password,mobile,real_name,create_time,accumulated_consumption_ammount,data_status,last_ip,version
FROM user LIMIT (0,9)

前端在刷新页面时把当前页码和页面展示条数发到后端,后端计算数据条数封装到limit进行查询

6.5 事务查询的实现

当用户增加员工时,员工表staff多了一条元组,所以此时也要讲部门表department的部门人数加1,这就是一个事务,要保证其原子性,要么都成功要么都失败,springboot对事务的处理是在方法名上添加@Transactional注解即可。

6.6 项目结构



前端项目的五个功能模块放在五个文件夹中。后端项目共有五个模块,大致分为网关加密、服务注册、后台服务三个功能微服务。

七、数据库实施

7.1数据库及数据库对象的SQL脚本文件:建表语句在附录(报告最后面)

7.2数据库备份和恢复方案

7.21备份策略的设计思路

备份是否完整,能否满足要求,关键还是要看所设计的备份策略是否合理,以及备份操作是否确实按照所设计的备份策略进行了。

针对不同的用途,所需要的备份类型是不一样的,备份策略也各有不同。如为了应对在线应用的数据丢失问题,备份就须要快速恢复,而且最好是只需要增量恢复就能找回所需数据。对于这类需求,最好是有在线的,且部分延迟恢复的备用数据库。因为这样可以在最短时间内找回所需要的数据。甚至在某些硬件设备出现故障的时候,将备用库直接开放,对外提供服务都可以。当然,在资源缺乏的情况下,可能难以找到足够的备用硬件设备来承担这个备份责任,也可以通过物理备份来解决,毕竟物理备份的恢复速度要比逻辑备份快很多。

而对于那些非数据丢失的应用场景,大多数时候恢复时间的要求并不是太高,只要能恢复出一个完整可用的数据库就可以了。所以不论是物理备份还是逻辑备份,影响都不是特别大。

可以根据不同的需求、不同的级别通过如下的几个思路来设计合理的备份策略:

1.对于较为核心的在线应用系统,必须有在线备用主机通过MySQL的复制进行相应的备份,复制线程可以一直开启,恢复线程可以每天恢复一次,尽量让备机的数据延后主机的时间在一定时间段之内。这个延后时间多长合适主要根据实际需求决定,一般来说延后一天是一个比较常规的做法。

2.对于重要级别稍微低一些的应用,恢复时间要求不是太高的话,为了节约硬件成本,不必使用在线的备份主机来单独运行备用MySQL,可以通过一定的时间周期进行一次物理全备份,同时每小时(或者其他合适的时间段)都将产生的二进制日志进行备份。这样虽然没有第一种备份方法恢复快,但是数据的丢失会比较少。恢复所需要的时间由全备周期长短决定。

3.对于恢复基本没有太多时间要求,但是不希望太多数据丢失的应用场景,则可以在一定时间周期内进行一次逻辑全备份,同时也备份相应的二进制日志。使用逻辑备份而不使用物理备份的原因是因为逻辑备份实现简单,可以完全在线联机完成,备份过程不会影响应用提供服务。

4.对于一些搭建临时数据库的备份应用场景,仅仅须要通过一个逻辑全备份即可满足需求,都不须要用二进制日志来进行恢复,因为这样的需求对数据并没有太苛刻的要求。

  • (上文部分参考于《MySQL性能调优与架构设计
    第五章 MySQL备份与恢复

》)

7.3数据库备份和恢复实践

备份test数据库到G盘的/bak.sql文件下

此时删除test数据库,然后再恢复test数据库。

成功。

根据经验与上课老师所言,应定期进行数据转储,制作后备副本。但转储又是十分耗费时间和资源的,不能频繁进行。DBA应该根据数据库使用情况确定适当的转储周期和转储方法。

数据库转储方案举例: 1.每天晚上进行动态增量转储 2.每周进行一次动态海量转储
3.每月进行一次静态海量转储

7.4日志基本操作

查看错误日志

慢查询日志

八、系统运行与维护

系统使用说明:2-3个程序运行的主要窗口的截图;具有代表性的功能的实现方法

的说明和主要代码(要有较完整的注释),要求能够体现程序设计中的重点和难点及设计者的能力及主要工作。

8.1 界面展示

8.1.1登录界面

8.1.2首页

8.1.3页面展示界面

有多分页展示的界面,结构类似,在此只展示两个主要页面,还有添加用户,编辑用户,删除用户的页面。

8.1.4数据统计界面

展示半年来各个商品的销量趋势

8.2系统代表性的功能

8.2.1雪花算法用户主键

不能使用数据库本身的自增功能来产生主键值,原因是生产环境为分片部署的,可能会分库。使用snowflake
(雪花)算法(twitter出品)生成唯一的主键值

1.41bit的时间戳可以支持该算法使用到2082年

2.10bit的工作机器id可以支持1024台机器

3.序列号支持1毫秒产生4096个自增序列id

4.整体上按照时间自增排序

5.整个分布式系统内不会产生ID碰撞

6.每秒能够产生26万ID左右

8.2.2 数据加密存储

采用BCrypt对数据进行加密后存放到数据库保证私密数据的安全性。BCrypt是使用哈希算法+随机盐来对字符串加密,用户登录验证密码时先将数据库中已经加密的密码取出,在后端服务器解密后再与前端发送的密码进行匹配。

数据库中被加密后的密码如上

8.2.3 接口加密传输

使用RSA对称秘钥算法加密,在前端服务器当用户请求时,用生成的公钥对接口请求的参数进行加密,网关在接收到加密后的数据时,用私钥解密后发到后端服务器进行处理,保证数据传输过程中的安全

前端配置加密的公钥,下面标注行则是调用加密函数把转换成json的数据进行加密


加密前后数据对比如上

8.2.3 并发问题的初步解决

使用乐观锁,对并发的线程冲突进行处理。考虑到可能多用户在同一时间对某用户进行更新操作,引发并发问题,采用乐观锁机制对用户表进行处理。在用户表中添加version字段,每次更新操作成功后,就将version+1。

例如:某元组user原先version值为1,当A线程对user执行了更新操作尚未提交时,B线程对同一user执行更新操作。此时B先完成了更新,version值变为2,此后当A线程commit时,发现version值改变,即撤销当前更新操作,只有B更新成功。

UPDATE user SET username=?, password=?, mobile=?, real_name=?, create_time=?,
accumulated_consumption_ammount=?, data_status=?, last_ip=?, version=? WHERE
id=? AND version=?

Parameters:jisooa(String),
$2a$10$HDuUxCXKrSGPLWePCA7SNeuYYMCptx7PEQxq.OHTaJgncF3qUDC1S(String),
1355987668(String), 金智秀(String), 2020-11-25T13:21(LocalDateTime),
500(Integer), false(Boolean), (String), 3(Integer), 123458434453832323(String),
2(Integer)


(media/3c4a83df6a9956a528abf170ed4e5859.png)]

8.2.4 非关系型数据库Redis的使用

在开发中使用Redis缓存加快数据搜寻,当用户登录浏览器,访问数据时,后端服务器会先查询缓存Redis是否存有数据,若Redis中没有数据,则从数据库中查出数据后,放到缓存中,下次查询时就不用查询数据库,且缓存查询速度很快,减少时间。

需要注意的是,把用户经常查询的数据放到缓存Redis中最好,可以大大提高查询速度,提高用户体验。

例如分页的数据要经常使用,放在Key为UserMap的缓存中,其余几个分页操作类似。

8.2.5 Java Web Token的使用

虽然有了接口加密,但是非法调用者如果知道服务器地址和端口地址的话,直接调用后端服务器接口可能会产生安全问题。

这时候就要在用户登录成功时,后台生成加密的token放到前端服务器中,token的payload中存放用户的id,以后前端每次发起请求时就把token加到请求头,这样只有通过服务器认证的用户才能正常访问后端服务器接口。

token如上

8.2.6 生产环境部署上线

本地开发环境是在Windows10系统下进行的,开发完后将前端服务器的项目build生成dist目录,在阿里云linux服务器上用nginx反向代理vue实现负载均衡部署;

后端服务器打成jar包后,也部署到阿里云服务器上。生产环境是Linux系统,版本是CentOS:7.3,mysql版本是5.7.32。

域名是http://39.108.136.207/#/login

项目采用了SpringCloud的微服务架构,微服务按需注册到eureka注册中心,一个微服务只关注一个特定的业务功能,本项目使用了网关加密微服务和用户后台服务,后续服务还会接着开发。

九、总结

收获与体会

通过课程设计,让我对数据库有了更进一步的认识,数据库操作也不仅仅是增删改查,数据库还有一系列的操作来保证数据的安全性和最小的冗余度,并在多用户同时使用数据时进行并发控制。在数据库设计的过程中,我认为概念模型、逻辑结构设计是最重要的步骤之一,好的概念模型设计可以真实地反应事物之间的联系,而好的逻辑结构则可以减少数据的冗余程度和操作异常。

当然,不止是DB,对DBMS的学习与使用也是让我受益匪浅。不同版本的mysql也对数据操作的支持不太一致,因此要根据实际DBMS的版本去合理使用。

此外,除了DB之外,本次项目采用了前后端分离的开发,虽然工作量很大但是收获和成就感也很大,在开发过程中,应当把系统数据安全放在首位,这次尝试使用了几种数据加密的方法,如jwt的HMAC256加密算法、接口加密的RSA加密算法、密码存储的ECYRPT哈希+盐的算法等。

一个好的项目应该是兼具功能性和好的用户体验,因此学习之路任重而道远。

系统需要改进的地方

  1. 前后端代码较多,可能有冗余部分。

  2. 数据库某些表数据量较少,后期会不断增加数据量。

  3. 对并发的处理只有对用户添加了乐观锁,保证了用户的并发问题。

  4. 开发时间有限,大部分时间用在开发,对系统的测试不够完善。

  5. 系统中对事务的处理较少,可能总共就只有两三个事务,一个是用触发器完成的,其余的都是用框架的事务处理功能去处理需要事务的方法。(涉及多表操作,所以是个事务)

十、附录

10.1建表语句

10.1.1 cashier表

CREATE TABLE `cashier` (

`cashier_id` char(10) NOT NULL COMMENT ‘收银台号’,

`start_time` datetime NOT NULL COMMENT ‘每天开始时间’,

`end_time` datetime NOT NULL COMMENT ‘每天结束时间’,

`cashier_ammount` int(10) NOT NULL COMMENT ‘台内账户金额’,

PRIMARY KEY (`cashier_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

10.1.2 commodidy表

CREATE TABLE `commodity` (

`cid` char(13) NOT NULL COMMENT ‘商品编号’,

`cname` char(10) NOT NULL COMMENT ‘名称’,

`price` int(10) NOT NULL COMMENT ‘基础售价’,

`promotion_start` datetime DEFAULT NULL COMMENT ‘促销开始日期’,

`promotion_end` datetime DEFAULT NULL COMMENT ‘促销结束日期’,

`discount_price` int(10) DEFAULT NULL COMMENT ‘折扣价’,

`stock` int(10) NOT NULL COMMENT ‘库存’,

`on_sale` smallint(2) NOT NULL COMMENT ‘是否可售’,

`wid` char(10) NOT NULL COMMENT ‘仓库号’,

PRIMARY KEY (`cid`),

KEY `commodity_wid` (`wid`),

CONSTRAINT `commodity_wid` FOREIGN KEY (`wid`) REFERENCES `warehouse`
(`wid`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

10.1.3 department表

CREATE TABLE `department` (

`did` char(13) NOT NULL COMMENT ‘部门编号’,

`dname` char(10) NOT NULL COMMENT ‘部门名称’,

`population` int(6) NOT NULL COMMENT ‘人数’,

`director` char(13) NOT NULL COMMENT ‘主管’,

PRIMARY KEY (`did`),

UNIQUE KEY `unique_dname` (`dname`) USING BTREE,

KEY `dept_director` (`director`),

CONSTRAINT `dept_director` FOREIGN KEY (`director`) REFERENCES `staff`
(`sid`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

10.1.4role表

CREATE TABLE `role` (

`rid` smallint(6) NOT NULL,

`role_name` char(10) NOT NULL,

PRIMARY KEY (`rid`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

10.1.5 sales表

CREATE TABLE `sales` (

`oid` char(20) NOT NULL COMMENT ‘订单编号’,

`cashier_id` char(10) NOT NULL COMMENT ‘收银台编号’,

`cid` char(13) NOT NULL COMMENT ‘商品编号’,

`number` int(10) NOT NULL DEFAULT ‘0’ COMMENT ‘数量’,

`date` datetime NOT NULL COMMENT ‘日期’,

`id` char(20) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT ‘用户编号’,

PRIMARY KEY (`oid`),

KEY `sales_id` (`id`),

KEY `sales_cid` (`cid`),

CONSTRAINT `sales_cid` FOREIGN KEY (`cid`) REFERENCES `commodity`
(`cid`),

CONSTRAINT `sales_id` FOREIGN KEY (`id`) REFERENCES `user` (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TRIGGER `number_insert` AFTER INSERT ON `sales` FOR EACH ROW BEGIN

UPDATE commodity as c SET c.stock =c.stock-(new.number) WHERE c.cid= new.cid ;

UPDATE commodity c, user as u SET u.accumulated_consumption_ammount
=u.accumulated_consumption_ammount + (new.number) * c.price WHERE c.cid=
new.cid AND u.id=new.id;

UPDATE commodity c, cashier as cs SET cs.cashier_ammount =cs.cashier_ammount
+(new.number)* c.price WHERE c.cid= new.cid AND cs.cashier_id=new.cashier_id ;

END;

CREATE TRIGGER `number_delete` AFTER DELETE ON `sales` FOR EACH ROW BEGIN

UPDATE commodity as c SET c.stock =c.stock+(old.number) WHERE c.cid= old.cid ;

UPDATE commodity c,user as u SET u.accumulated_consumption_ammount
=u.accumulated_consumption_ammount - (old.number) * c.price WHERE c.cid=
old.cid AND u.id=old.id;

UPDATE commodity c, cashier as cs SET cs.cashier_ammount =cs.cashier_ammount
-(old.number)* c.price WHERE c.cid= old.cid AND cs.cashier_id=old.cashier_id ;

END;

10.1.6 staff表

CREATE TABLE `staff` (

`sid` char(13) NOT NULL COMMENT ‘员工号’,

`sname` char(10) NOT NULL COMMENT ‘姓名’,

`ssex` char(2) NOT NULL COMMENT ‘性别’,

`position` char(10) NOT NULL COMMENT ‘职称’,

`sage` smallint(6) NOT NULL COMMENT ‘年龄’,

`salary` char(10) NOT NULL COMMENT ‘工资’,

`did` char(13) NOT NULL COMMENT ‘部门号’,

`cashier_id` char(13) DEFAULT NULL COMMENT ‘收银台号’,

PRIMARY KEY (`sid`),

KEY `staff_did` (`did`),

KEY `staff_cashierId` (`cashier_id`),

CONSTRAINT `staff_cashierId` FOREIGN KEY (`cashier_id`) REFERENCES
`cashier` (`cashier_id`),

CONSTRAINT `staff_did` FOREIGN KEY (`did`) REFERENCES `department`
(`did`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TRIGGER `insert_sage` BEFORE INSERT ON `staff` FOR EACH ROW begin

if(NEW.Sage<66 AND NEW.Sage >= 18) THEN

SET@choice=1;

ELSE

SET@choice=0;

INSERT INTO staff VALUES(1);

end if;

end;

CREATE TRIGGER `update_sage` BEFORE UPDATE ON `staff` FOR EACH ROW begin

if(NEW.Sage<66 AND NEW.Sage >= 18) THEN

SET@choice=1;

ELSE

SET@choice=0;

INSERT INTO `staff` VALUES(1);

end if;

end;

10.1.7 supplier表

CREATE TABLE `supplier` (

`supplier_id` char(10) NOT NULL COMMENT ‘供应商编号’,

`supplier` char(20) NOT NULL COMMENT ‘供应商名称’,

`mobile` char(11) NOT NULL COMMENT ‘电话’,

`sid` char(13) NOT NULL COMMENT ‘员工编号’,

PRIMARY KEY (`supplier_id`),

KEY `supplier_sid` (`sid`),

CONSTRAINT `supplier_sid` FOREIGN KEY (`sid`) REFERENCES `staff` (`sid`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

10.1.8 supply表

CREATE TABLE `supply` (

`cid` char(13) NOT NULL COMMENT ‘商品编号’,

`supplier_id` char(10) NOT NULL COMMENT ‘供应商编号’,

`number` int(10) NOT NULL COMMENT ‘数量’,

`supply_price` char(10) NOT NULL COMMENT ‘供应单价’,

`date` datetime NOT NULL COMMENT ‘供应日期’,

PRIMARY KEY (`cid`,`supplier_id`),

KEY `supply_supplierId` (`supplier_id`),

CONSTRAINT `supply_cid` FOREIGN KEY (`cid`) REFERENCES `commodity`
(`cid`),

CONSTRAINT `supply_supplierId` FOREIGN KEY (`supplier_id`) REFERENCES
`supplier` (`supplier_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

10.1.9 user表

CREATE TABLE `user` (

`id` char(20) NOT NULL COMMENT ‘用户编号’,

`username` char(20) NOT NULL DEFAULT ‘’ COMMENT ‘用户名’,

`password` varchar(200) NOT NULL DEFAULT ‘’ COMMENT ‘密码,用户使用’,

`mobile` char(11) NOT NULL DEFAULT ‘’ COMMENT ‘手机号’,

`real_name` char(10) NOT NULL DEFAULT ‘’ COMMENT ‘真实姓名’,

`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘创建时间’,

`accumulated_consumption_ammount` int(10) NOT NULL DEFAULT ‘0’ COMMENT
‘累计消费金额’,

`last_ip` varchar(16) DEFAULT ‘’ COMMENT ‘最后登录ip’,

`data_status` tinyint(1) NOT NULL DEFAULT ‘1’,

`version` int(10) DEFAULT ‘1’ COMMENT ‘乐观锁’,

`rid` smallint(6) NOT NULL DEFAULT ‘4’ COMMENT ‘角色id’,

PRIMARY KEY (`id`),

UNIQUE KEY `mobile` (`mobile`),

UNIQUE KEY `username` (`username`) USING BTREE,

KEY `user_rid` (`rid`),

CONSTRAINT `user_rid` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘用户表’;

10.1.10 warehouse表

CREATE TABLE `warehouse` (

`wid` char(10) NOT NULL,

`address` char(20) NOT NULL,

`sid` char(13) NOT NULL,

PRIMARY KEY (`wid`),

KEY `warehouse_sid` (`sid`),

CONSTRAINT `warehouse_sid` FOREIGN KEY (`sid`) REFERENCES `staff`
(`sid`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

10.2建视图语句

10.2.1 一月商品销量视图

CREATE VIEW january AS

SELECT DISTINCT s.cid ,c.cname, IFNULL(january,0) january

FROM commodity c,sales s LEFT OUTER JOIN

(SELECT s.cid, c.cname, SUM(number) january

FROM sales s, commodity c

where date BETWEEN ‘2021-01-01’ AND ‘2021-01-31’ AND s.cid = c.cid

GROUP BY s.cid) j ON (s.cid=j.cid)

where c.cid=s.cid

其余五个月类似,在此不做展示

10.2.2 上半年商品销量视图

CREATE VIEW report1

AS

SELECT DISTINCT j.cid ,j.cname, january,february,march,april,may,june,
(january+february+march+april+may+june)/6 as 月平均销量

FROM january j,february f,march m,april a,may,june

WHERE j.cid=f.cid AND f.cid=m.cid AND m.cid=a.cid AND a.cid=may.cid AND may.cid
= june.cid

2021年数据库课设该怎么做?一个超市管理系统,简单的前后端分离项目,带你从概要设计走到项目发布!(Vue.js+SpringBoot+MybatisPlus)相关推荐

  1. HNUST - 数据库课设

    HNUST - Python+Mysql数据库课设 一.实验题目 人事管理系统 二.实验目的 企业人事管理系统主要用于员工个人资料的录入.职务变动的记录和管理.使用人事管理系统,便于公司领导掌握人员的 ...

  2. 数据库课设(足球联赛管理系统)

    一:前言 如果有关注博主的粉丝,可能会发现贴心杰又缺更好几天了,但是我是宠粉杰啊,怎么可能会忘了我的宝贝粉丝呢,只不过是临近期末,各种大作业课设如期而至,这几天我在写数据库课设,对于一个没有写过任何项 ...

  3. 广东工业大学数据库课设(点歌系统)

    摘 要 本论文主要是对卡拉OK点歌系统的设计过程,后端设计,前端设计,数据库设计的分析.结合软件工程已经数据库系统概论所学知识,详细内容是系统的实现背景,设计过程,功能的实现以及部分的个人感悟. 前言 ...

  4. 数据库课设记录 Day 3

    Day 3 经过各种斟酌,砍了不少一时心血来潮想做的东西,数据库课设的核心内容就定下来了. 公司 Company 名称 字段 数据类型 id id int 公司名 name varchar(20) 地 ...

  5. 【数据库课设】学生成绩管理系统 (JAVA+ swing + JDBC)

    正道的光 源代码资源获取!!!!! 百度网盘: https://pan.baidu.com/s/1fQab5mOfpZ14rv7yhT_TAQ 提取码:0307 Github: https://git ...

  6. 数据库课设项目(上) 医院

    文章目录 任务 需求分析 过程 CREATE DATABASE 导入地区数据 转义字符 CREATE TABLE 成功导入 注册医院 CREATE TABLE 导入结果 触发器创建默认科室 初始科室 ...

  7. JAVA+MySQL 数据库课设的问题及解答的整理 以【学生管理系统】为例

    JAVA+MySQL 数据库课设的问题及解答的整理 以[学生管理系统]为例.帅气学长哦! 编写这篇博文初衷 MySQL的一些问题 Eclipse导入项目的一些问题 数据库的建立和连接 最后一步 编写这 ...

  8. 数据库课设项目(下) 医护人员与患者

    文章目录 任务 过程 随机身份数据 CREATE TABLE Resident python代码打印SQL语句 实现结果 医生信息 CREATE TABLE Doctor 导入数据 "升职& ...

  9. 代写SOFTENG 370 Operating Systems课设、代做C/C++ 留学生作业、代写c/c++代码、代写C/C++编程作业...

    代写SOFTENG 370 Operating Systems课设.代做C/C++ 留学生作业.代写c/c++代码.代写C/C++编程作业 SOFTENG 370 Operating Systems ...

最新文章

  1. .中英文系统底层编码导致乱码问题
  2. html 注释_java基础- Java编程规范与注释
  3. python 单点登录_清华园计算机系联合推出的Java+Python视频曝光
  4. 12月23号 Foundation库NSString操作
  5. wifi情况下使用fiddler_钢筋网片在什么情况下使用?
  6. Linux 目录文件处理文件
  7. python 仪表盘 ppt_Python强大的pyecharts绘画优美图形lt;三gt;
  8. SQL Server中 char与varchar
  9. GCD 信号量控制并发 (dispatch_semaphore)
  10. RocketMQ源码学习(六)-Name Server
  11. 字符串算法 金策_OI-Public-Library/国家集训队论文1999-2017 at master · BlackWaters/OI-Public-Library · GitHub...
  12. win10怎样更改系统字体_掌阅F1系统设置及字体更改、水墨屏阅读软件、打卡必备软件...
  13. 推荐几款常用在线代码转换工具
  14. java计算机毕业设计糖果销售管理系统源码+系统+数据库+lw文档+mybatis+运行部署
  15. 《Java核心技术》学习笔记——第8章 泛型程序设计
  16. group normalization
  17. Datawhale团队第二期录取名单!
  18. 2023-spring 2.探险营地 — 字符串
  19. 每周荐书:架构、Scratch、增长黑客(评论送书)
  20. Hector代码原理推导

热门文章

  1. 一种锂电池充电器的设计方案(使用LM317)
  2. 【FPGA】Verilog实现奇偶分频
  3. 区块链在数字版权领域的应用发展报告(2020)
  4. Vulkan_Shader_Day01—光照(物体颜色)
  5. 抖音上热门原来这么简单-抖音培训-抖音上热门教程
  6. svn造成桌面图标显示问号的处理办法
  7. PaMIR: Parametric Model-Conditioned Implicit Representation for Image-based Human Reconstruction
  8. 整理了一些常用的免费 API 接口,不限次数,收藏备用!(持续更新...)
  9. python爬虫抓网页的总结
  10. 单片机c语言idata什么意思,单片机C语言中的data,idata,xdata,pdata,code