建模工具
有一说一,我觉得,对于我个人来说,Navicat是绰绰有余了
在项目需求分析之后基本就到了E-R实体图的物理建模流程,那么有一款好工具是必须的
传统经典(商用付费):SAP PowerDesigner |数据建模和企业架构
关于ER-图和这些工具,有一篇文章写的很好,可以一看:【PowerDesigner】一款超好用的E-R图工具,快速构建出高质量的数据库结构,提高开发效率和代码质量自动生成er图的工具是瑶瑶子啦的博客-CSDN博客
comment '分类级别:0->1级;1->2级'注释字段,显得规范主键,bigint not null auto_increment,足够大的数字、不为空,自增长。主键的声明放在语句的最后,primary key (id)default 设置初始的默认值字段锁机制:添加一个version版本号类似的字段来锁定状态规避少量的并发。对于大量并发这个手段不一定能凑效但也是一种方法状态字段:在数据库表中一般使用不同的数字来定义不同的状态或者等级。而不是直接用字符串“会员”、“普通用户”这样来标示的。同时比如用户账号一般不会直接注销而是尽量引入“软状态”,如启用、禁用...也就是尽量不物理删除而是逻辑删除del_flag(tinyint(1))只取0和1经常变更的字段:如果我们要在数据库中存储一些格式不固定的属性时,可以采用JSON的形式进行存储,比如商品就有SU的概念,又比如元数据和标签我们自定义的东西同时又不作为检索需求的就可以使用JOSN字符存储。对于关联属性的修改,可以通过一些逻辑操作来实现不改变原有属性的修改。如果经常变更而且和业务不太相关的数据我们甚至可以使用MongoDB这样的非关系型数据库存储内容复杂且庞大的数据:先将数据转换成JSON格式再装换成Blog格式存储进数据库表的Blog类型的内容字段中。因为JSON是目前最主流的数据传送和解析格式,跨平台的交互性好同时将数据转为 JSON 格式后再存储为 Blob 类型字段,可以通过压缩算法来减少存储空间的占用。特别是对于包含大量重复或冗余信息的文本数据,压缩可以显著降低存储需求。我看知名的开源博客项目Halo就是用这种方式存储文章和插件数据的。当然了在使用这种设计方式时,可能会存在一些潜在的问题和限制,例如查询和索引的性能可能不如传统的表结构,以及部分数据库可能对 JSON 数据的操作支持有所差异。因此,在具体应用中,需要权衡利弊并根据具体需求进行选择。文本字符类型的选择:
varchar 更合适。如果字符串长度固定,并且需要提高比较、排序和索引的性能,使用 char 更合适。text类型是更合适的选项。相较于varchar类型,text类型的最大容量限制更高,可以容纳更多的字符数据。可以存储任意长度的文本数据,使其适用于存储大段的描述、文章或其他长文本内容。此外,text类型通常还具备一些特殊的功能,例如全文搜索和文本处理函数,可以在需要对文本内容进行高级搜索、匹配和处理的情况下发挥作用。Longtext):如果文章内容非常大,超过了 Text 类型的范围,可以选择使用 Longtext 类型的字段来存储。Longtext 类型适合存储较长或大块的文本数据。媒体:二进制类型(Blob),如图片、音频或视频等多媒体文件,可以使用 Blob 类型的字段来存储。Blob 类型可以容纳任意二进制数据。你可以将多媒体文件转换为字节流,然后将其存储在 Blob 字段中。像一些博客的文章内容若包含各种媒体文件也可以考虑使用包含二进制数据的Blog来存储。
数字型字段
decimal 数据类型。这个数据类型可以指定精确小数位数,并提供更高的精度。例如,price、promotion_price、original_price、weight等字段可以选择 decimal(10,2) 类型,表示最多10位数,其中2位是小数部分。时间、日期字段
对于存储日期的字段,可以使用 date 数据类型。例如,promotion_start_time 和 promotion_end_time 字段可以选择 date 类型,用于存储促销活动的开始日期和结束日期。
对于存储具体时间的字段,可以使用 time 数据类型。然而,在实际应用中,更常见的是需要存储日期和时间的组合。这种情况下,可以使用 datetime 或 timestamp 数据类型。
datetime 数据类型存储日期和时间的组合,并且具有固定的格式(例如:2023-06-28 10:18:17)。适用于需要精确到秒的时间记录。
timestamp 数据类型也用于存储日期和时间的组合,但是它以自 1970 年 1 月 1 日以来经过的秒数来表示,通常用于记录时间戳。注意,timestamp 数据类型对时区敏感,会根据服务器设置自动进行转换。
例如,promotion_start_time 和 promotion_end_time 字段可以选择 datetime 或 timestamp 类型,用于存储促销活动的具体开始时间和结束时间。
需要注意的是,我还见到两种方案:这两种方式相比起来各有优劣可以在恰当的地方恰当使用
varchar等字符类型存储时间bigint等用时间戳形式存储时间尽可能的拆分粒度,一张表只有一个关系通过连接表联系起来;一张额外的表在基础权限上额外为单个用户增加权限。
ums_admin:后台用户表ums_role:后台用户角色表ums_permission:后台用户权限表ums_admin_role_relation:后台用户和角色关系表,用户与角色是多对多关系ums_role_permission_relation:后台用户角色和权限关系表,角色与权限是多对多关系ums_admin_permission_relation:后台用户和权限关系表(除角色中定义的权限以外的加减权限),加权限是指用户比角色多出的权限,减权限是指用户比角色少的权限RABC是基于角色的访问控制(Role-Based Access Control)的缩写。在访问控制领域,RABC是一种常见的访问控制模型,用于管理系统中的用户权限。该模型通过将用户分配到角色上,并为每个角色分配相应的权限,来实现对系统资源的访问控制。
RABC模型中包含以下几个关键概念:
用户(User):系统中的实体,可以是个人用户、程序或其他系统。
角色(Role):对用户的一种抽象,代表一组具有相似权限需求的用户集合。通常根据用户的职责、职位或功能划分角色。
权限(Permission):指允许用户或角色执行的操作或访问的资源。权限可以是对文件、数据库、网络服务等的访问,也可以是对特定功能的执行权限。
许可(Grant):将权限授予角色的过程。许可将特定的权限分配给特定的角色。
请求(Request):用户或程序向系统发出的对资源访问的请求。
访问控制策略(Access Control Policy):用于描述哪些角色拥有哪些权限,并规定了用户或角色如何通过请求来获得访问权限。
通过RABC模型,系统管理员可以根据角色来管理用户的权限,从而简化权限管理的复杂性。相比直接给每个用户分配权限,使用角色可以更好地组织和管理权限,提高系统的安全性和可维护性。
很多表在数据库设计的时候因为继承关系的设计最终会呈现树状的结构,常见的就是评论表、课程表等通过父子id键值来完成关系绑定的表。举例如下:
课程分类在数据库中是以一张表的形式存储的(parrentId),是一个树状存储结构:因为有大分类和小分类,大分类下很多小分类多以采取树状结构存储。子子分类再继承子分类,那就是子子孙孙无穷尽也。对于这样的表我们该如何查询?
问题其实无外乎就是:如何生成一个树型结构的对象?
因为最后转换成JSON对象便于我们解析读取,假如需求确定知道分类是多少(即明确知道分类下有多少子分类也就是知道要遍历的深度)**可以使用表的自连接,那方法自然而然有:
这里我们选第2种方案,因为第一种方法感觉有些许蠢了,。下面是基于Springboot应用和Mybatis的案例应用:
1、下边 定义一个mapper方法,并定义sql语句。
public interface CourseCategoryMapper extends BaseMapper<CourseCategory> {
List<CourseCategoryTreeDto> selectTreeNodes();
}
找到对应 的mapper.xml文件,编写sql语句。
<select id="selectTreeNodes" resultMap="treeNodeResultMap" >
select
one.id one_id,
one.name one_name,
one.parentid one_parentid,
one.orderby one_orderby,
one.label one_label,
two.id two_id,
two.name two_name,
two.parentid two_parentid,
two.orderby two_orderby,
two.label two_label
from course_category one
inner join course_category two on one.id = two.parentid
where one.parentid = 1
and one.is_show = 1
and two.is_show = 1
order by one.orderby,
two.orderby
</select>
2、编写resultMap
<!-- 课程分类树型结构查询映射结果 -->
<resultMap id="treeNodeResultMap" type="com.xuecheng.content.model.dto.CourseCategoryTreeDto">
<!-- 一级数据映射 -->
<id column="one_id" property="id" />
<result column="one_name" property="name" />
<result column="one_label" property="label" />
<result column="one_parentid" property="parentid" />
<result column="one_orderby" property="orderby" />
<!-- 一级中包含多个二级数据:二级的集合数据 -->
<collection property="childrenTreeNodes" ofType="com.xuecheng.content.model.dto.CourseCategoryTreeDto">
<!-- 二级数据映射 -->
<id column="two_id" property="id" />
<result column="two_name" property="name" />
<result column="two_label" property="label" />
<result column="two_parentid" property="parentid" />
<result column="two_orderby" property="orderby" />
</collection>
</resultMap>
不确定可以使用Mysql8.0的新特性递归SQL语法(貌似在性能上不太好),像Oracle其实很早之前就有这样的语法【还没用过呢,。】
没用过,。下次一定?!
MySQL在设计和查询树状表时可能会比较麻烦和繁琐,而MongoDB则更适合处理树状结构的数据。MongoDB是一种面向文档的NoSQL数据库,具有灵活的数据模型和便于处理嵌套和层次结构的能力。
在MongoDB中,可以使用嵌套文档或者引用文档的方式来表示树状结构,而不需要使用递归、自连接等复杂的SQL操作。对于树状表的查询,MongoDB提供了强大的聚合管道功能,可以方便地进行树状结构的遍历和查询。
如果数据具有明显的树状结构,并且需要频繁进行树状表的查询和操作(比如评论树),那么使用MongoDB可能会更加简单和高效。
先删后添
如果一张表的数据更新涉及多个变化其实不妨直接删除然后再直接添加新的最终结果。
举个例子,向权限表更新没必要去比较前后的变化,可以直接将权限项直接删除,然后添加最新的权限结果。(前提:记录的消失不会引起关联影响)