我正在开发旅行管理应用程序。有问题的设计如下:
巡回演出中的每个人都被指定为旅行者。 每位旅行者都有护照。 现在,旅行者可以是主会员或子会员,具体取决于他是否是家庭主管。 MainMember决定TourPackage,旅行家庭的总金额等等。 SubMember在旅行时依赖于MainMember。因此,如果删除了MainMember,则还必须删除其所有SubMembers。
所以, 旅行者有护照。 (一对一的关系) 旅行者是主会员或子会员。 (Traveler-MainMember和Traveler-SubMember之间的一对一/一) MainMember可能有几个SubMembers。 (一到多) SubMember只有一个MainMembers。 (多到一个)
我目前的ERD如下:
正如您所看到的,三个表 - Traveler,MainMember和SubMember--形成了循环依赖。不过,我不确定它是否会伤害我的应用程序。 如果我删除了一个MainMember的旅行者,那么 1.删除Traveler的记录。 2.删除其相关的MainMember记录。 3.删除依赖于MainMember的SubMember记录。 4.删除子成员的旅行者记录。
虽然它似乎不是问题,但Traveler-MainMember删除将始终只删除Traveler-SubMember。不过,我对此感觉不好。
有人能引导我进行更好的设计吗?
更新 -
在等待回复的同时,我根据@ Daveo的回复提出了另一个设计。基本上,Traveler包含自引用外键。 SubMember记录将使用它来识别他们的父母。
这是ERD。
现在,正如@Branko指出的那样,我之前的设计中没有循环依赖问题,我想知道哪种设计更好?
另外,通过Hibernate实现哪种设计会更好?我认为第二种方法可能会在通过Hibernate实现时导致复杂性。
我也很欣赏有关您喜欢的设计的实现模式(Hibernate实体中的继承等)的一些指示。
答案 0 :(得分:5)
正如您所看到的,三个表 - Traveler,MainMember和SubMember - 形成了循环依赖。
不,这不是循环依赖 - 此图中的“节点”不能通过遵循正确方向 1 的图形“边缘”来实现。它将更准确地描述为“合并”或甚至(原型)“菱形”依赖。
不,它不会伤害你的申请。 2
您正在有效地实现继承(也就是类别,子类,子类型,泛化层次结构等),使用“单独表中的每个类”方法。这种方法很简洁,但不能保证存在 3 和排他性 4 开箱即用。 有amend it这样的方法,并且还有其他的继承实现策略可以,但它们有自己的pros and cons。
在我看来,你的模型对你想要完成的事情很好,并且在应用程序级别强制执行存在/排他性可能比在数据库级别尝试强制执行它的缺点更为邪恶。
1 “Direction”来自引用表。 Traveller
未引用MainMember
或SubMember
,因此会打破周期。
2 除非您使用的DBMS(例如MS SQL Server)不支持对此类“合并”依赖项的引用操作(在这种情况下,您需要实现ON CASCADE通过触发器删除)。
3 Traveller
不能单独存在(不能是“抽象”),必须是MainMember
或SubMember
。 < / p>
4 Traveller
不能同时为MainMember
和SubMember
。
答案 1 :(得分:1)
我在数据库中只有两个表。
旅行者和密码
Traveler将有一个Parent_Id字段,该字段将链接回Traveler表并存储Main / Head旅行者的身份。 还存储此表中Main / Sub成员共有的字段,如联系号码
然后使用继承和ORM在实际应用程序中创建两个不同的类。 MainMember和SubMember MainMember将是Traveler中Parent_Id为null的所有行 SubMember将是Traveler中Parent_Id不为空的所有行