目录
PARTY
PARTY_ROLE
PARTY_RELATIONSHIP
PARTY_RELATIONSHIP_TYPE
PARTY_CLASSIFICATION_TYPE
PARTY_CLASSIFICATION_GROUP
PARTY_CLASSIFICATION
CONTENT_MECH
CONTENT_MECH_TYPE
PARTY_CONTACT_MECH
CONTACT_MECH_PURPOSE_TYPE
PARTY_CONTACT_MECH_PURPOSE
CONTENT_TYPE
CONTENT
PARTY_CONTENT_TYPE
总结
更高的抽象级别
数据库表的继承关系
时效性设计
首页 数据库 mysql教程 谈ApacheOFbiz会员模块表结构设计

谈ApacheOFbiz会员模块表结构设计

Jun 07, 2016 pm 04:12 PM
会员 数据库 模块 结构设计

数据库表的结构设计可谓是ofbiz除技术框架之外,另一个非常值得学习的方向。这篇文章我们来谈谈ofbiz对电子商务会员表的设计。 PARTY ofbiz对人、团体进行了抽象,称之为party,翻译为中文称之为“会员”(但我觉得抛开领域,如果你也有相关的设计需求,在其

数据库表的结构设计可谓是ofbiz除技术框架之外,另一个非常值得学习的方向。这篇文章我们来谈谈ofbiz对电子商务会员表的设计。

PARTY

ofbiz对人、团体进行了抽象,称之为party,翻译为中文称之为“会员”(但我觉得抛开领域,如果你也有相关的设计需求,在其他领域可能称之为团体更合适)。会员在ofbiz被设计为一个抽象的概念(对应到面向对象设计中,你可以称其为一个基类),它有两个具体的延伸(继承者):分别是PERSON以及PARTY_GROUP。数据库的E-R图:

\

这里PERSON,PARTY_GROUP分别表示“个人会员”、“组织会员”。Party只是一种抽象,它定义了可以被抽象为“会员”的对象所具有的基本特征。但 “个人”以及“组织”会员却具备比 “基本会员”更多的特征,所以此处从Party延伸出两张表来存储这些额外的特征信息它们的主键都是PARTY表的PARTY_ID。
喎?http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD48aDE+UEFSVFlfVFlQRTwvaDE+PHA+cGFydHlUeXBltqjS5cHLcGFydHm1xMDg0M3UvMr4oaNFLVLNvMjnz8KjujxiciAvJmd0OzwvcD48cD48aW1nIHNyYz0="http://www.2cto.com/uploadfile/Collfiles/20141208/2014120809092365.png" alt="\" />

可以看到,PARTY_TYPE是拥有层级关系的(它的一个属性PARENT_TYPE_ID自关联了PARTY_TYPE的主键:PARTY_TYPE_ID,下面如果看到E-R图上有自关联到本身的,都表示这种关系,不再敖述)。

ofbiz提供的初始数据中有如下几种party type:

\

构建成层级关系如下图所示:

\

上面展示的两张表:PERSON、PARTY_GROUP也是其中的两个partyType,并且这些partyType都可以独立扩展的,PERSON、PARTY_GROUP也是仅有的两个扩展。这也是上面表结构中这两个记录的HAS_TABLE值为Y的原因。

PARTY_ROLE

就跟社会的“角色分工”一样,一个会员在系统中也必定会拥有属于自己的角色。而PARTY_ROLE表就是用于关联会员与角色类型的关系表,很明显会员与角色类型是多对多的关系(这里需要提及的是:ofbiz中只有角色类型,没有角色,或者更准确点说,角色类型包含了角色)。

\

PARTY_RELATIONSHIP

上面我们看到的会员是一类“抽象”的实体。不管它表示的是个人,还是组织,它总是会跟其他会员发生关系,就好像一个人不可能脱离社会而孤立得存在着,他必然有自己的社会角色,并跟社会的其他“团体”产生联系。这在ofbiz中被抽象为“partyRelationship”。我们来看它是如果表达“关系”这个语义的:

\

当你把这些所有的字段连起来,它几乎能涵盖所有的“会员关系”(要知道,有时会员关系会非常复杂,一个会员有时会存在于多个系统中)。

我们再回过头来,看PARTY_RELATIONSHIP的表结构设计:

\

可以看到前五个键形成了联合主键,其中前四个都是形如XXX_FROM,XXX_TO的ID标识。表示从“FROM”方往“TO”方建立关系。其中PARTY_ID_FROM与ROLE_TYPE_ID_FROM是“源”方;PARTY_ID_TO与ROLE_TYPE_ID_TO是“目标”方。

从上面图中也可以看到,每个关系都带有两个DATETIME字段,分别表示:开始日期,截止日期。这说明关系是有“时段”这个属性的。当然,如果没有截止日期,可以看做是“永久”的。因此为了防止关系过了生效时段无法再次建立关系(因为主键不允许重复),所以选择了联合“FROM_DATE”作为联合主键(后面如果再次建立相同的关系时,只要FROM_DATE不一样,就视为一条新记录)。

这里有必要说明一下,在ofbiz的数据库设计中,大量采用了“时段”这个属性来标识记录的有效性。这样的设计与逻辑删除相比的好处是:它除了减少了删除时因为外键约束等连带关系导致的错误,还可以直接充当“历史记录”的作用,省去了对历史表的维护,当然它的缺点就是:表中的记录会比其他的设计多得多。

当然,From跟To只是为了标识两者建立了关系,却并未说明它们到底存在怎样的关系,就好像——我跟你是朋友。这句话可以拆分为三部分:FROM方:我,TO方:你,关系是:朋友。上表中用一个字段表示了关系:PARTY_RELATIONSHIP_TYPE_ID(这只是一个外键,关联着表PARTY_RELATIONSHIP_TYPE)。

在界面上新建一个关系(此处是从外部到自己的一个关系):

\

PARTY_RELATIONSHIP_TYPE

该表约束了关系的类型。比如:雇佣者、朋友、父、子、管理者,E-R图:

\

从图中可以看出,会员关系类型也拥有层次关系。表中还有两个特别的字段:

ROLE_TYPE_ID_VALID_FROMROLE_TYPE_ID_VALID_TO
它们用于约束这个关系的建立双方的角色。也就是说,不是任意的两个角色之间一定可以建立起某个特定的会员关系。当然这两个字段通常都为空,表示不对此加以限制。
对每个关系类型,都可以扩展以独立实现关系(被扩展后关系类型记录的字段HAS_TABLE被标识为Y,否则默认为N),在ofbiz的初始化数据中,唯一被扩展的关系类型是:EMPLOYMENT。我们来看看EMPLOYMENT关系表的实现:
\
可以看到,它跟之前的PARTY_RELATIONSHIP的主键实现方式一样。因此可以把它看做是:PARTY_RELATIONSHIP_TYPE_ID为EMPLOYMENT的PARTY_RELATIONSHIP的特殊实现。
在界面上建立一个关系类型:
\

PARTY_CLASSIFICATION_TYPE

为了便于管理,ofbiz对会员按各种维度进行分类,常见的分类的类型有:年收入、价值等级、产业、雇员数量等;

PARTY_CLASSIFICATION_GROUP

会员并不会直接跟分类的类型产生关系,而是跟一个或多个分类组产生关联关系。而分类组受分类类型约束。
新建一个分类组:
\

PARTY_CLASSIFICATION

会员的分类相关表的关系图:
\
从表的关联关系可以看出,会员分类跟分类组是多对多的关系,并且分类具有时效性。因此联合FROM_DATE作外键。
将会员划归入一个会员分类:
\

CONTENT_MECH

从这张表开始,我们来看会员的联系方式相关的表结构设计,这也是一部分非常棒的设计。\
这张表存储了联系方式基本信息。它引用了另一张表:CONTENT_MECH_TYPE作为外键,来表示该联系方式的类型(通常的联系方式类型有电话、邮箱、网址等)。

CONTENT_MECH_TYPE

\
可以看到联系方式类型,也是具有层级结构(父子关系)的。
当我们想新建一个联系方式时,首先必须先指定想创建的联系方式的类型:
\

PARTY_CONTACT_MECH

毫无疑问,地址信息只有跟会员联系起来,才能表示会员的地址。而会员跟地址是多对多的关系,理解这个关系时需要注意的是会员可以是任何团体、组织或者个人。那这里可能就会存在两个不同的会员拥有同一个联系方式的可能,比如:一个员工会员与一个该员工所属的公司会员,它们可以都存在同一个联系方式:公司的通讯地址。当然一个会员拥有多个联系方式,这是很容易理解的。所以会员标识跟联系方式标识之间是多对多的关系,并且跟前面的设计模式相似——联系方式也有时效性,比如换电话号码,换工作导致联系方式变化等,所以联合FROM_DATE作为联合主键:
\
当我们选择联系方式类型为电话号码时,会出现如下的表单填写:
\
如果你新建一个联系方式的类型为电话号码,那么电话号码存储在何处?此处又跟前面谈到的HAS_TABLE字段有关(CONTACT_MECH_TYPE中也存在这个字段)。正常情况下,联系方式关联着联系方式类型,普通的联系方式的具体信息存储在CONTACT_MECH的INFO_STRING属性中。但有些联系信息不是单纯的像邮箱这样只是一个字符串,比如像电话号码、邮政编码…它们都有具体的格式表示。所以这些特例用INFO_STRING这一个属性存储也不方便,因此可以独立扩展该CONTACT_MECH_TYPE(将其HAS_TABLE字段设置为Y,这样查询该CONTACT_MECH信息的时候,就不采用INFO_STRING字段,而是采用扩展表中格式化的联系方式)。

CONTACT_MECH_PURPOSE_TYPE

当我们点击上面界面的保存按钮之后,会更进一步得扩充联系信息:
\
在ofbiz中还存在一个称之为“联系目的”的东西,它是什么意思?
\
看到选项我们就会明白,说白了一个人的地址簿或者电话簿中的联系方式可能有很多。它们没有主次之分,只有目的不同。

PARTY_CONTACT_MECH_PURPOSE

上面谈到了联系目的,那么很自然它需要跟会员具体的某条联系信息关联起来才能称之为:某个会员为了某种联系目的存储了一个“联系方式”记录。
\
这里需要注意的是,它并没有跟PARTY_CONTACT_MECH产生直接关联(没有外键关系),而是把PARTY_CONTACT_MECH的三个主键照搬过来,联合CONTACT_MECH_PURPOSE_TYPE_ID形成四个组合主键,这是因为PARTY_CONTACT_MECH的联合主键机制无法被其他表当做外键引用。因此,可以将PARTY_CONTACT_MECH_PURPOSE看作联系信息模块的聚合。这个怎么来理解?其实一个地址可以看成:某个会员(PARTY_ID),出于某种目的(CONTACT_MECH_PURPOSE_TYPE_ID),在某段时间内(FROM_DATE),保存了某个联系方式(CONTACT_MECH_ID)。这种联系方式的设计非常有弹性,因此在大部分情况下,这种抽象性能够涵盖大部分应用场景。

CONTENT_TYPE

会员内容的设计跟联系方式类似。会员可以有一个类似文件空间在服务器上,可以供其保存文档、图片之类的东西。CONTENT_TYPE限定了会员可以存储的内容类型:
\

CONTENT

该表是它的具体存储内容的地方,当然并不是唯一的,如果CONTENT_TYPE有一条记录的HAS_TABLE值为Y,则那个记录对应的表也用于存储内容。内容表里的字段非常多,就不截图了。
跟之前的联系信息类似,会员可以有多个内容,一个内容也可能从属于多个会员。因为会员是个抽象的概念,对应到实体上可能会有重合,所以需要一个“目的”来修饰会员内容,它就是——PARTY_CONTENT_TYPE。

PARTY_CONTENT_TYPE

用于修饰会员内容的用途,当然这里它的表名叫type,事实上从数据记录来看,来时充当了目的的作用。
\
内容还跟其他一些表有关联(主要是被引用关系,比如:CONTENT_ROLE等),此处因为跟本文主题没太大关系,所以不再敖述。

总结

更高的抽象级别

ofbiz party模块的设计,正如它所应用的场景:非常适用于电子商务系统会员信息相关的设计。当然ofbiz中其他相关的多个系统也同样应用了这些表结构,这也意味着它有适用于一般行业、系统的通用性,这得益于这种设计的抽象级别比较高。它可以描述任何的组织、个体、他们的地址信息、他们之间的关系。特别是对会员“relationship”表的设计非常类似于《分析模式》中谈到的责任模式:
系统的用户,又或者一个非常大的跨国公司,拥有:总部、区域销售办公室、办事处、分公司等各种组织形式时,这种设计就会派上用场。

数据库表的继承关系

从PARTY、PARTY_TYPE、PARTY_GROUP、PERSON这几张表我们可以学习到数据库表的“继承”设计。

时效性设计

不是真删除、也不是逻辑删除、而是失效(FROM_DATE, THUR_DATE)。这种方式可以代替“操作-操作历史”的多表设计,转而合并为独立的一张表。
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

iOS 18 新增'已恢复”相册功能 可找回丢失或损坏的照片 iOS 18 新增'已恢复”相册功能 可找回丢失或损坏的照片 Jul 18, 2024 am 05:48 AM

苹果公司最新发布的iOS18、iPadOS18以及macOSSequoia系统为Photos应用增添了一项重要功能,旨在帮助用户轻松恢复因各种原因丢失或损坏的照片和视频。这项新功能在Photos应用的"工具"部分引入了一个名为"已恢复"的相册,当用户设备中存在未纳入其照片库的图片或视频时,该相册将自动显示。"已恢复"相册的出现为因数据库损坏、相机应用未正确保存至照片库或第三方应用管理照片库时照片和视频丢失提供了解决方案。用户只需简单几步

在PHP中使用MySQLi建立数据库连接的详尽教程 在PHP中使用MySQLi建立数据库连接的详尽教程 Jun 04, 2024 pm 01:42 PM

如何在PHP中使用MySQLi建立数据库连接:包含MySQLi扩展(require_once)创建连接函数(functionconnect_to_db)调用连接函数($conn=connect_to_db())执行查询($result=$conn->query())关闭连接($conn->close())

如何在PHP中处理数据库连接错误 如何在PHP中处理数据库连接错误 Jun 05, 2024 pm 02:16 PM

PHP中处理数据库连接报错,可以使用以下步骤:使用mysqli_connect_errno()获取错误代码。使用mysqli_connect_error()获取错误消息。通过捕获并记录这些错误信息,可以轻松识别并解决数据库连接问题,确保应用程序的顺畅运行。

微信小程序怎么弄会员 微信小程序怎么弄会员 May 07, 2024 am 10:24 AM

1、打开微信小程序,进入对应的小程序页面。2、在小程序页面中查找会员相关入口,通常会员入口在底部导航栏或个人中心等位置。3、点击会员入口,进入会员申请页面。4、在会员申请页面,填写相关信息,如手机号码、姓名等,完成信息填写后,提交申请。5、小程序方会对会员申请进行审核,审核通过后,用户即可成为微信小程序会员。6、作为会员,用户将享有更多的会员权益,如积分、优惠券、会员专属活动等

如何在 Golang 中使用数据库回调函数? 如何在 Golang 中使用数据库回调函数? Jun 03, 2024 pm 02:20 PM

在Golang中使用数据库回调函数可以实现:在指定数据库操作完成后执行自定义代码。通过单独的函数添加自定义行为,无需编写额外代码。回调函数可用于插入、更新、删除和查询操作。必须使用sql.Exec、sql.QueryRow或sql.Query函数才能使用回调函数。

如何用 Golang 连接远程数据库? 如何用 Golang 连接远程数据库? Jun 01, 2024 pm 08:31 PM

通过Go标准库database/sql包,可以连接到MySQL、PostgreSQL或SQLite等远程数据库:创建包含数据库连接信息的连接字符串。使用sql.Open()函数打开数据库连接。执行SQL查询和插入操作等数据库操作。使用defer关闭数据库连接以释放资源。

PEPU币币种介绍 PEPU币币种介绍 Dec 12, 2024 am 11:43 AM

PEPU 币是一种基于以太坊区块链的 ERC-20 代币,由 PEPU.io 运营并被用作其 PEPU 应用程序中的原生代币。

如何使用C++处理数据库连接和操作? 如何使用C++处理数据库连接和操作? Jun 01, 2024 pm 07:24 PM

在C++中使用DataAccessObjects(DAO)库连接和操作数据库,包括建立数据库连接、执行SQL查询、插入新记录和更新现有记录。具体步骤为:1.包含必要的库语句;2.打开数据库文件;3.创建Recordset对象执行SQL查询或操作数据;4.遍历结果或按照具体需求更新记录。

See all articles