SimpleAdmin手摸手教学之:关联关系

一、前言

在传统的开发中,我们有用户user表,有角色role表,有菜单menu表,这些表代表着一个“实体”,而我们想把user和role关联,就会创建user_role关联表,想把role和menu关联,就会创建一个role_menu表,其实关联表创建多了,我们就不难发现,他们的结构大致是相同的,就是以一个“对象”关联另一个“对象”,并以其唯一键进行关联,可能还会冗余保存双方的一些额外的“扩展信息”。以上是小诺文档对于为何取消use_role,role_men这种关系表,而是采用一张relation表来记录各者之间的关系的说明,本人十分认可这种设计方式,这样只需要用一张表就可以代表多张关系表,可以少写很多实体和服务,只需一个实体和服务,然后根据不同分类获取不同的关系。

二、基本说明

启动项目后,会发现有client_relation,dev_relation和sys_relation三张“关系”表,这三张表其实结构一模一样,打开任意一张表,发现其结构如下:

Id:本条关系的主键,不存在具体的意义,仅仅是为了增删改查方便,实际业务中不会去关心这个“关系”的主键,关心的是双方的信息。

ObjectId:对象ID,这个字段是一种抽象的含义,表示要关联的数据的ID,这里存在一个“主动”关系,就是谁要关联的,这个ID就是谁,比如用户关联角色,其表示用户ID,角色关联菜单ID,其表示角色ID

TargetId:目标ID,这个字段也是一种抽象的含义,表示被关联的数据ID,同理,就是谁是“被动”的,这个ID就是谁,比如用户关联角色,其表示角色ID,角色关联菜单ID,其表示菜单ID。

特别注意一点,千万不要被目标ID的“ID"这个词迷惑,只是大多数情况表达对方数据的主键ID,但是并不完全一定,比如在本框架中,角色和API接口的关系,其表示的就是接口API本身,因为接口是从系统中扫描出来的,并没有在数据库中人为的管理,所以不存在“ID”的说法。

另外,这个字段也可为空,被关联方的信息比较大,且没有主键信息的情况下,可以将数据存储在ExtJson字段,比如本框架中有个“自定义”工作台的功能,ObjectId表示用户ID,其工作台数据就是存储在ExtJson中的。因此这张表的用处不应该局限的看,既然是关系表,那应该可以存储一切关系类型。

Category:关系类型,这个是非常重要的字段,表示关联类型,光有对象ID和目标ID还不够,不知道这个关系表达什么意思,所以这个字段用来区分这个关系的含义,系统不会对这个含义进行限制,由使用者自行定义,比如用户关联角色,这个字段值本框架定义为SYS_USER_HAS_ROLE,角色关联资源本框架定义为SYS_ROLE_HAS_RESOURCE。

ExtJson:扩展数据,这个表示额外的关系数据,比如角色和菜单关联时,还需要顺便存储菜单下的按钮ID,这样就可以表示该角色和哪些菜单,以及和该菜单下的哪些按钮产生了关系。值得注意的是,这个字段存储的应该是该条关系的“扩展数据”或者“整体数据”,被关联数据的主键信息依然要存储在TargetId,在角色和菜单关系中,菜单ID才是主要被关联的,而不是按钮ID。

三、项目中使用

在本系统中,你可以在RelationService中找到相关的方法,并且本系统已经对该表进行了缓存处理,大大减少了读取时间。

Redis数据结构如下:

可以看到所有的关系都通过Category 分别存储在了不同的key里,而不是一个key存储所有的关系,这样就不会造成读取无用数据的问题,同时我们存和取只需要根据Category 来就好了,非常清晰。

posted @ 2023-01-08 09:56  HuTiger  阅读(2052)  评论(1编辑  收藏  举报