我可以在多大程度上扩展JPA集合(地图或列表)

时间:2016-01-04 05:59:07

标签: jpa jpa-2.0

我正在通过JPA实现相当于由SQL数据库支持的在线文件系统。对于目录层次结构,我创建了一个如下所示的实体:

@Entity
@Table(name = "PATH")
public class Path extends BaseObject implements Serializable {

    @Column(nullable = false)
    private String name;

    @ManyToOne
    private BaseObject reference;

    @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true)
    @MapKey(name = "name")
    private Map<String, Path> members;

    @ManyToOne
    private Path parent;

    //etc

这非常好用。根节点是路径实例,其中为空。通过这种方案,我可以上下进行树遍历,并尽可能轻松地查找。

问题是这可以缩放多远。例如,我的一个根路径实例将为系统的每个用户提供一个成员。对于几十个甚至几百个用户来说这很好,如果我的网站吸引了数十甚至数十万用户,会发生什么?

如果必须,我可以放弃成员列并找到具有SQL SELECT 操作的成员节点,但我讨厌这样做。是否有任何指导方针可以确定 Map 结构在变得不切实际之前必须达到多大?

1 个答案:

答案 0 :(得分:1)

默认情况下,members关联是懒惰的。所以在加载Path时不会发生任何不好的事情,直到......你开始使用这个members字段(即调用它上面的任何方法)。然后成千上万的孩子将被装入记忆中,并且根本不会很好地扩展。但使用专用查询不会更好:成千上万的孩子也会被加载到内存中。

问题在于......你应该简单地避免在内存中加载路径的所有子节点。您不需要这样做来创建具有现有父级的新路径。您可能必须这样做才能在屏幕上显示路径的所有子项,但如果您有数千个这样的子项,那么这是不现实的,因此您最好使用分页查询通过切片显示它们20或50。

所以,我确实会放弃这个过于危险的OneToMany关联,并使用即席查询来获取所需的子项。我更关心的是与父母的联系。由于您已将它们定义为急切加载(这是toOne关联的默认值),因此每次加载路径时,JPA都会加载其父级,祖父级和祖父级等,直到根。如果树很深,这可能会有问题。您最好将关联定义为懒惰(基本上所有关联都是这样做的。)

最后,请注意您的映射不正确。你在这里有一个双向关联,OneToMany members因此是ManyToOne parent的反面,所以它应该用

注释
@OneToMany(mappedBy = "parent", orphanRemoval = true)