我有一些巫师,他们分别属于魔术的各个分支。成为一个教派的成员会赋予您特殊的能力,您可以使用这些能力来打败敌人。这些教派中的一些教派具有一些教派,这些教派会赋予您其他权力。

@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) == trueoak.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中删除。所以我真的会在Spell类上引用Sect,然后将它们全部添加到Sect和子分区中。但这似乎也需要大量维护,并且容易出错。

另一种选择是保留整个拼写提供结构的缓存,并且只要产品中的某些内容发生变化,只需清空表并对其进行重构。当我编辑咒语产品时,这将是一项昂贵的操作,但这是相当罕见的情况。

理想情况下,我有一个运行并获取所需信息的HQL(我想我可以做NamedNative ...,但要避免的话)。但是我不知道如何构造这样的查询,如果我这样做了,那么如何使其不能完全糟透了。

我有没有想到的选择?有什么工具或技巧吗?我知道休眠有很多技巧!

最佳答案

编写Sect时,添加一个方法

isSubsectOf(Sect s)


如果此教派是其他教派的一个教派,则返回true。它是递归的,因此它返回aprent sec,祖父母宗派等。现在您可以通过以下方式检查向导是否是该宗派的成员:


测试他是否直接是该教派的成员
测试他所属的教派是否是它的一个分支


为了完整起见,您可能还想写一些列出给定宗派的所有父项等。

要检查能力,请在Sect'canCast(Spell sp)'上编写一个方法,该方法不仅检查它是否在该Sect的咒语列表中,而且还检查所有父Sect。如果canCast(Spell sp)对于特定成员所属的Sect返回true,则向导可以施放咒语。

这是直接的Java继承,不需要任何复杂的操作

关于java - 分层所有权导致请求缓慢,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20008900/

10-10 15:35