避免循环依赖 [英] Avoid Circular Dependency

查看:219
本文介绍了避免循环依赖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发旅行管理应用程序。有关设计如下:



旅游中的每个人都被指定为旅行者。
每位旅客都有护照。
现在,旅行者可以是主会员或子会员,这取决于他是否是家庭的负责人。
主要会员决定像TourPackage,旅行家庭的总金额等等。
一个子会员在旅行时依赖MainMember。所以,如果一个MainMember被删除,所有的SubMembers也必须被删除。



所以,
旅行者有护照。 (一对一关系)
旅行者是主会员或子会员。 (Traveler-MainMember和Traveler-SubMember之间一到零/一个)
主成员可能有几个SubMembers。 (一对多)
一个SubMember只有一个MainMembers。 (多对一)



我目前的ERD如下。





正如你所见,三个表 - 旅行者,主成员和子成员 - 已经形成循环依赖。我不知道是否会伤害我的应用程序。
如果我删除一个主要会员的旅行者,那么
1.来自Traveler的记录被删除。
2.其相关MainMember记录被删除。
3.删除与MainMember相关的SubMember记录。
4. SubMembers的Traveler记录被删除。



虽然这似乎不是一个问题,但由于Traveler-MainMember删除将始终只会删除旅行者分会员。不过,我对此感到不舒服。



任何人都可以指导我进行更好的设计?



更新 -



在等待回复时,我根据@ Daveo的回复提出了另一个设计。基本上,旅行者包含自我引用的外键。它将被子成员记录用于识别他们的父母。



这是ERD。





现在,就像那里在我以前的设计中没有循环依赖的问题,如@Branko所指出的,我想知道哪种设计更好?



另外,哪种设计会更好通过Hibernate实现?我认为第二种方法可能会导致复杂性,同时通过Hibernate实现。



我还将了解一些关于实现模式(Hibernate实体继承等)的指针,

解决方案


如您所见,三个表 - Traveler,MainMember和SubMember - 已经形成循环依赖关系。


不,这不是循环依赖关系 - 此图中的节点无法达到自身通过以正确方向 1 之后的图形边缘。它将被更准确地描述为合并或甚至(原型)菱形依赖。



不,它不会伤害你的应用程序。 2



您正在有效地实现继承(也称为类别,子类,子类型,泛化层次等),使用每个类在单独表的方法。这种方法是干净的,但是不能保证出现 3 和排他性 4
有什么方法可以修改它,所以它还有其他的继承实现策略可以,但是他们有自己的利弊



在我看来,您的模型对于您正在尝试完成的任务以及在应用程序级别执行存在/排他性来说可能更糟糕,而不是在数据库级别尝试执行它的缺点。






1 方向是从引用到引用的表。 旅行者不引用 MainMember SubMember ,因此中断循环。



2 除非您使用的是不是的DBMS(如MS SQL Server)支持对这种合并依赖性的引用操作(在这种情况下,您需要通过触发器实现ON CASCADE DELETE)。



3 Traveler 不能单独存在(不能是抽象),它必须是 MainMember SubMember



4 不能同时使用 MainMember SubMember


I am developing a travel management application. The design in question is something like following :

Each person in a tour is designated as a Traveler. Each Traveler has a Passport. Now, a Traveler can be a MainMember or a SubMember, depending on whether or not he is the head of the family. A MainMember decides stuff like TourPackage, total amount for his travelling family, etc. A SubMember is dependent on the MainMember while travelling. So, if a MainMember is deleted, all its SubMembers have to be deleted as well.

So, A Traveler has a Passport. (One to One relationship) A Traveler is either a MainMember or a SubMember. (one-to-zero/one between Traveler-MainMember and Traveler-SubMember) A MainMember may have several SubMembers. (one-to-many) A SubMember has only one MainMembers. (many-to-one)

My current ERD is something as follows.

As you can see, the three tables - Traveler, MainMember and SubMember - have formed a circular dependency. I am not sure if it will hurt my application, though. If I delete a Traveler who is a MainMember, then 1. A record from Traveler is deleted. 2. Its relevant MainMember record is deleted. 3. The SubMember records dependent on MainMember are deleted. 4. The Traveler records of SubMembers are deleted.

Though it doesn't seem to be a problem, as a Traveler-MainMember delete will always delete only Traveler-SubMember(s). Still, I have a bad feeling about this.

Can anyone guide me to a better design?

UPDATE -

While waiting for the replies, I came up with another design, based on @Daveo's reply. Basically, Traveler contains self-referential foreign key. It would be used by the SubMember records to identify their parents.

Here is the ERD for that.

Now, as there was no issue of circular dependency in my previous design, as pointed by @Branko, I would like to know which design is better?

Also, which design would be better to implement through Hibernate? I think the second approach might lead to complexity while implementing through Hibernate.

I would also appreciate some pointers regarding the implementation patterns (inheritance in Hibernate entities, etc.) for the design that you prefer.

解决方案

As you can see, the three tables - Traveler, MainMember and SubMember - have formed a circular dependency.

No, this is not a circular dependency - no "node" in this graph can reach itself by following graph "edges" in their proper direction1. It would be more accurately described as "merged" or even (proto) "diamond-shaped" dependency.

And no, it will not hurt your application.2

You are effectively implementing inheritance (aka category, subclassing, subtyping, generalization hierarchy etc.), using "each class in separate table" approach. This approach is clean, but cannot guarantee presence3 and exclusivity4 out of box. There are ways to amend it so it does, and there are other implementation strategies for inheritance that can, but they have their own pros and cons.

In my opinion, your model is just fine for what you are trying to accomplish and enforcing the presence/exclusivity at the application level is probably lesser evil than suffering the cons of trying to enforce it at the database level.


1 "Direction" is from referencing to referenced table. Traveller doesn't reference MainMember nor SubMember and therefore breaks the cycle.

2 Unless you are on a DBMS (such as MS SQL Server) that doesn't support referential actions on such "merged" dependencies (in which case you'd need to implement ON CASCADE DELETE through triggers).

3 Traveller cannot exist alone (cannot be "abstract"), it must be MainMember or SubMember.

4 Traveller cannot be both MainMember and SubMember.

这篇关于避免循环依赖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆