ER关系字段

抽象实体路径

在实体关系图中,多对多关系用于表示两个实体之间的关系。多对多关系是具有传递性的。例如,如果实体A与实体B具有多对多关系,而实体B与实体C具有多对多关系,则实体A和实体C也具有多对多关系,这是一种间接的多对多关系。

基于多对多关系的传递性,抽象实体路径的概念被提出用于描述实体之间这种直接或间接的多对多关系。抽象实体路径将从一个实体到另一个实体的所有实体作为节点来描述任意两个实体之间所具有的多对多关系。例如,实体A和实体B的抽象实体路径为[A,B],实体B和实体A的抽象实体路径为[B,A],实体C和实体A的抽象实体路径为[C,B,A]。抽象实体路径包含了任意两个实体之间关系的全部信息,从而用于动态生成复杂的嵌套查询语句。

GoooQo 引入抽象实体路径概念,定义名为entitypath的标签来表示实体之间的关系。该标签用于查询对象中的用于查询实体关系的字段。例如,实体路径`entitypath:"user,role"`,基于预定的表名格式,可以得到两个实体表名t_user和t_role,中间表表名a_user_and_role,以及两个外键名称user_id和role_id,进而生成查询语句:

SELECT * FROM t_user WHERE
id IN (
    SELECT user_id FROM a_user_and_role WHERE role_id IN (
       SELECT id FROM t_role WHERE ...
    )
)

示例

t_menu 有一个列 parent_id,它将 id 列本身引用为外键。parent_id 列用于定义菜单项之间的层次父子关系。菜单通过通用 RBAC 模型作为系统资源分配给用户。那么菜单到用户的实体路径即为:menu,perm,role,user,用于生成嵌套查询语句。

import . "github.com/doytowin/goooqo/core"

type MenuEntity struct {
	IntId
	ParentId *int    `json:"parentId,omitempty"`
	Name     *string `json:"name,omitempty"`
}

type MenuQuery struct {
	PageQuery
	Id *int

	// many-to-one:
	// 查询特定父菜单的子菜单:
	// parent_id IN (SELECT id FROM t_menu WHERE [conditions])
	Parent *MenuQuery `entitypath:"menu" localField:"ParentId"`

	// one-to-many:
	// 查询特定子菜单的父菜单:
	// id IN (SELECT parent_id FROM t_menu WHERE [conditions])
	Children *MenuQuery `entitypath:"menu" foreignField:"ParentId"`

	/**
	many-to-many:
	查询特定用户可以访问的菜单:
	id IN (
		SELECT menu_id FROM a_perm_and_menu WHERE perm_id IN (
			SELECT perm_id FROM a_role_and_perm WHERE role_id IN (
				SELECT role_id FROM a_user_and_role WHERE user_id IN (
					SELECT id FROM t_user WHERE [conditions]
				)
			)
		)
	)*/
	User *UserQuery `entitypath:"menu,perm,role,user"`
}

最后更新于