分层所有权导致请求缓慢

时间:2013-11-15 19:19:39

标签: java hibernate inheritance

我有一些巫师属于各种魔法派。作为一个教派的成员授予你特殊的权力,你可以用来击败你的敌人。其中一些教派有子部分,授予你额外的权力。

@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和Maple中。但是,如果一个咒语是由地球上也发现的Oak明确提供的呢?如果我从地球教学中删除它,它不应该从Oak中删除。所以我真的会参考Spell类上的Sect,然后将它们全部添加到Sect和子部分。但这似乎也很多维护和容易出错。

另一个选择是保持整个法术提供结构的缓存,并且每当产品中的某些内容发生变化时,只需清空表并重新构建它。当我编辑法术时,这将是一项昂贵的操作,但这种情况相当罕见。

理想情况下,我有一个单独的HQL(我想我可以做NamedNative ......但我想尽可能避免)查询运行并获取我需要的信息。但我不知道如何构建这样的查询,如果我这样做,如何使它不完全吮吸。

我有没有想到的选择?任何工具或技巧?我知道hibernate有很多技巧!

1 个答案:

答案 0 :(得分:1)

编写Sect时,添加方法

isSubsectOf(Sect s)

如果此Sect是其他部分的子部分,则返回true。它是递归的,所以它返回aprent sec,祖父母教派等。现在你可以通过

检查一个巫师是否是一个教派的成员
  • 测试他是否直接成为该教派的成员
  • 测试他所属的教派是否是其中的一个子部分

为了完整起见,你可能还想写一些东西,列出给定教派的所有父母等教派。

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

这是简单的Java继承,不需要任何复杂的