-
Notifications
You must be signed in to change notification settings - Fork 35
数据库中Treelike表统一树形结构管理
吴达 edited this page Dec 25, 2020
·
1 revision
在数据库设计中,通常使用ID-ParentID这样的模式表示上下级关系,最常见的就是category表的设计,比如
CREATE TABLE IF NOT EXISTS `item`.`item_category` (
`item_category_id` BIGINT UNSIGNED NOT NULL,
`category_name` VARCHAR(45) NOT NULL COMMENT '分类名称',
`parent_id` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '父级分类ID'
PRIMARY KEY (`item_category_id`)
)
COMMENT = '商品分类'
使用parent_id表示上级,这种表示上下级的方式在数据库设计中很通用,而且在一个系统中,通常有多个表都是这样的结构,比如文章分类表,部门,组织机构等等。这种类型的表我们可以认为是tree-like的表,因为可以表示树形结构。
每个表自身有单独的业务逻辑,除了这些独有的业务逻辑外,对于树形结构方面,他们有很多操作是相同的,比如
- 新增,更新时,同一个父节点下不能有同名的节点
- 删除时,如果下级还有子节点,则不能被删除
- 获取某个节点的children,祖先,后裔列表
- 生成树形结构
- 为前端生成方便展示成树形结构的JSON
- 改变节点的父级时,维护树的完整性,比如节点的depth(level)的维护
- 等等
既然在树形结构方面有这么多相同的操作,因此,是否可以统一管理Tree-like表在树形结构方面的操作呢?答案是可以,按照功能的不同,我们给出了以下几类解决方案
- 统一维护Tree-like数据库表
- 统一为前端生成方便展示树形结构的JSON
- 统一生成Tree数据结构,方便内存中的查找操作(比如查询祖先,后裔等等)
- 为所有具有ID-parentID特点的数据提供工具类,因为这种类型的数据可以表示上下级关系,因此,只要数据有这种特点,都可以方便的通过工具方法操作树形结构相关的内容
TreeManager接口用于定义Tree-like相关表的增,删,改,查操作
抽象实现类用于完成共有的逻辑(类似JDBC模板代码的实现),比如:
- 检查正在创建的节点是否根节点,如果不是,则该节点的父节点必须存在
- 同一个父节点下不允许出现同名的节点
- 维护节点的depth(level),如果节点可以移动,则这个功能的效果更能显现 抽象类已经实现了很多逻辑,具体的子类,只需要实现对具体表的简单的增,删,改,查方法即可,比如item_category表的简单增删改查
每个公司的前端要求的格式可能不一样,这里我们提供一种可能的格式
Treeable组件
Treeable组件序列化成JSON后,结构如下
* {
* "node": {
* "name": "湖南省",
* "id": 2,
* "pid": 1
* },
* "children": [{
* "node": {
* "name": "张家界市",
* "id": 3,
* "pid": 2
* },
* "children": [{
* "node": {
* "name": "桑植县",
* "id": 5,
* "pid": 3
* },
* "children": null
* }]
* }, {
* "node": {
* "name": "长沙市",
* "id": 4,
* "pid": 2
* },
* "children": null
* }]
* }
对于Tree-like表的记录,我们可以方便的生成Treeable实体,从而统一为前端提供树形结构,方便展示
我们能够统一的管理树形结构,最核心的特点就是:数据具有id-parentId关系的特点,因此我们把这类数据抽象为IdPidEntry,然后提供了相关的工具类IdPidEntryUtils
不用多说了,就是树形结构
给定扁平的IdPidEntry集合,我们就可以通过IdPidEntryTreeBuilder这个类生成Tree结构,因为数据之间具有id-parentId relationship,因此,肯定可以生成Tree
架构
数据库设计
约定
基础工具
DataType模块
Property模块
权限模块