我有一些巫师属于各种魔法派。作为一个教派的成员授予你特殊的权力,你可以用来击败你的敌人。其中一些教派有子部分,授予你额外的权力。
@Entity
public class Sect {
private long id;
private String name;
private Sect parent;
@ManyToMany
private Set<Spell> spells;
}
@Entity
public class Wizard {
private long id;
private String name;
@ManyToMany
private Set<Sect> sects;
}
现在,我有一个巫师,他是橡树勋章的成员。橡树的顺序是森林秩序的一个分支,而森林顺序又是地球秩序的一个分支。 (所以wizard.sects.contains(oak) == true
和oak.parent.parent.equals(earth) == true
)。法术“地球螺栓”由地球秩序授予。我的向导并非明确地是地球秩序的成员,甚至不是森林秩序的成员。他是由橡树勋章的成员招募的。但是,他是隐含的成员,可以访问所有这些法术。现在,我基本上是这样做的:
boolean canCast(Wizard wizard, Spell spell) {
Queue<Sect> toProcess = new ...
toProcess.addAll(wizard.getSects());
Set<Sect> processed = new ...
while(!toProcess.isEmpty()) {
Sect sect = toProcess.poll();
if(!processed.add(sect)) continue; // already did this from a sister sect
toProcess.add(sect.getParent());
if(sect.getSpells().contains(spell))
return true;
}
return false;
}
但是当我真的不需要时,将所有这些信息都拉回来似乎很愚蠢。
我知道我有几个选项,比如保存父订单的表格,所以当你加入橡树之勋时,它会把你加入森林秩序和地球秩序,但这似乎很难看。如果你从橡树之躯中删除了它并且它删除了森林和地球......那么如果你也是枫树勋章的一部分怎么办呢?你仍然会在森林和地球。这只是一个案例 - 我敢肯定有很多案例会在我脸上爆炸。
另一种选择是跟踪地球和森林中的法术并将它们放入Oak和Maple中。但是,如果一个咒语是由地球上也发现的Oak明确提供的呢?如果我从地球教学中删除它,它不应该从Oak中删除。所以我真的会参考Spell类上的Sect,然后将它们全部添加到Sect和子部分。但这似乎也很多维护和容易出错。
另一个选择是保持整个法术提供结构的缓存,并且每当产品中的某些内容发生变化时,只需清空表并重新构建它。当我编辑法术时,这将是一项昂贵的操作,但这种情况相当罕见。
理想情况下,我有一个单独的HQL(我想我可以做NamedNative ......但我想尽可能避免)查询运行并获取我需要的信息。但我不知道如何构建这样的查询,如果我这样做,如何使它不完全吮吸。
我有没有想到的选择?任何工具或技巧?我知道hibernate有很多技巧!
答案 0 :(得分:1)
编写Sect时,添加方法
isSubsectOf(Sect s)
如果此Sect是其他部分的子部分,则返回true。它是递归的,所以它返回aprent sec,祖父母教派等。现在你可以通过
检查一个巫师是否是一个教派的成员为了完整起见,你可能还想写一些东西,列出给定教派的所有父母等教派。
要检查能力,请在Sect'canCast(Spell sp)'上编写一个方法,该方法不仅检查它是否在该Sect的法术列表中,还检查所有父Sects的法术列表。如果canCast(Spell sp)为他是特定成员的Sect返回true,则向导可以施放咒语。
这是简单的Java继承,不需要任何复杂的