数据库表的结构设计可谓是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)。这种方式可以代替“操作-操作历史”的多表设计,转而合并为独立的一张表。
MySQL中的SQL命令可以分为DDL、DML、DQL、DCL等类别,用于创建、修改、删除数据库和表,插入、更新、删除数据,以及执行复杂的查询操作。1.基本用法包括CREATETABLE创建表、INSERTINTO插入数据和SELECT查询数据。2.高级用法涉及JOIN进行表联接、子查询和GROUPBY进行数据聚合。3.常见错误如语法错误、数据类型不匹配和权限问题可以通过语法检查、数据类型转换和权限管理来调试。4.性能优化建议包括使用索引、避免全表扫描、优化JOIN操作和使用事务来保证数据一致性

InnoDB通过undolog实现原子性,通过锁机制和MVCC实现一致性和隔离性,通过redolog实现持久性。1)原子性:使用undolog记录原始数据,确保事务可回滚。2)一致性:通过行级锁和MVCC确保数据一致。3)隔离性:支持多种隔离级别,默认使用REPEATABLEREAD。4)持久性:使用redolog记录修改,确保数据持久保存。

MySQL在数据库和编程中的地位非常重要,它是一个开源的关系型数据库管理系统,广泛应用于各种应用场景。1)MySQL提供高效的数据存储、组织和检索功能,支持Web、移动和企业级系统。2)它使用客户端-服务器架构,支持多种存储引擎和索引优化。3)基本用法包括创建表和插入数据,高级用法涉及多表JOIN和复杂查询。4)常见问题如SQL语法错误和性能问题可以通过EXPLAIN命令和慢查询日志调试。5)性能优化方法包括合理使用索引、优化查询和使用缓存,最佳实践包括使用事务和PreparedStatemen

MySQL适合小型和大型企业。1)小型企业可使用MySQL进行基本数据管理,如存储客户信息。2)大型企业可利用MySQL处理海量数据和复杂业务逻辑,优化查询性能和事务处理。

InnoDB通过Next-KeyLocking机制有效防止幻读。1)Next-KeyLocking结合行锁和间隙锁,锁定记录及其间隙,防止新记录插入。2)在实际应用中,通过优化查询和调整隔离级别,可以减少锁竞争,提高并发性能。

MySQL不是一门编程语言,但其查询语言SQL具备编程语言的特性:1.SQL支持条件判断、循环和变量操作;2.通过存储过程、触发器和函数,用户可以在数据库中执行复杂逻辑操作。

MySQL是一种开源的关系型数据库管理系统,主要用于快速、可靠地存储和检索数据。其工作原理包括客户端请求、查询解析、执行查询和返回结果。使用示例包括创建表、插入和查询数据,以及高级功能如JOIN操作。常见错误涉及SQL语法、数据类型和权限问题,优化建议包括使用索引、优化查询和分表分区。

MySQL是一个开源的关系型数据库管理系统,适用于数据存储、管理、查询和安全。1.它支持多种操作系统,广泛应用于Web应用等领域。2.通过客户端-服务器架构和不同存储引擎,MySQL高效处理数据。3.基本用法包括创建数据库和表,插入、查询和更新数据。4.高级用法涉及复杂查询和存储过程。5.常见错误可通过EXPLAIN语句调试。6.性能优化包括合理使用索引和优化查询语句。


热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Dreamweaver Mac版
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

SublimeText3 Linux新版
SublimeText3 Linux最新版

WebStorm Mac版
好用的JavaScript开发工具

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。