java - Hibernate 中层次结构的高效表示

标签 java hibernate orm tree graph

我在 Hibernate 中表示对象层次结构时遇到了一些问题。我四处搜索,但未能找到任何执行此操作或类似操作的示例 - 如果这是一个常见问题,我深表歉意。

我想使用 Hibernate 坚持使用两种类型:组和项。
* 组由其名称和父组的组合唯一标识。
* 组排列在许多树中,这样每个组都有零个或一个父组。
* 每个项目可以是零个或多个组的成员。

理想情况下,我想要一种双向关系,让我能够:
* 项目所属的所有组
* 属于特定组或其后代的所有项目。
我还需要能够从顶部遍历组树,以便在 UI 上显示它。

理想情况下,基本对象结构如下所示:

class Group {
    ...
    /** @return all items in this group and its descendants */
    Set<Item> getAllItems() { ... }

    /** @return all direct children of this group */
    Set<Group> getChildren() { ... }
    ...
}

class Item {
    ...
    /** @return all groups that this Item is a direct member of */
    Set<Group> getGroups() { ... }  
    ...
}

最初,我只是在 Items 和 Groups 之间建立了一个简单的双向多对多关系,这样获取组层次结构中的所有项目需要递归到树下,而获取一个 Item 的组是一个简单的 getter ,即:

class Group {
    ...
    private Set<Item> items;
    private Set<Group> children;
    ...
    /** @return all items in this group and its descendants */
    Set<Item> getAllItems() {
        Set<Item> allItems = new HashSet<Item>();
        allItems.addAll(this.items);
        for(Group child : this.getChildren()) {
            allItems.addAll(child.getAllItems());
        }
        return allItems;
    }

    /** @return all direct children of this group */
    Set<Group> getChildren() {
        return this.children;
    }
    ...
}

class Item {
    ...
    private Set<Group> groups;
    /** @return all groups that this Item is a direct member of */
    Set<Group> getGroups() {
        return this.groups;
    }
    ...
}

但是,这会导致多个数据库请求获取具有许多后代的组中的项目,或者检索整个组树以显示在 UI 中。这似乎非常低效,尤其是对于更深、更大的组树。 在 Hibernate 中是否有更好或标准的方式来表示这种关系?

我有没有做错或愚蠢的事情?


到目前为止,我唯一的想法是: 用指定组的整个祖先的唯一“路径”字符串替换组的 id、parent 和 name 字段,例如:
/根组
/rootGroup/aChild
/rootGroup/aChild/aGrandChild

Groups 和 Items 之间的连接表将包含 group_path 和 item_id。

这立即解决了我之前遇到的两个问题:
1. 整个组层次结构可以在一次查询中从数据库中获取并在内存中重建。
2. 要检索组中的所有项目或其后代,我们可以从 group_item 中选择 group_path='N' 或 group_path like 'N/%'

然而,这似乎违背了使用 Hibernate 的意义。欢迎所有想法!

最佳答案

我认为真正的问题是您希望性能受到哪些影响。如果你宣称你所有的关系都是懒惰的,并拉出你需要的东西,那么你会随着时间的推移分散打击。在许多情况下,这意味着您的用户(人或芯片)感知到更快的 react 时间。即使您一次处理整个图,您实际上也不需要同时将整个图存储在内存中。

另一方面,将整个图表拉到一起可以预先提高性能,同时加快操作速度。

两者之间的最大区别在于您的具体用例。如果这是一个网络服务器,将整个图形拉入内存杀死服务器。无论如何,大多数人无法处理超过 7-10 个选项,而且整个图表很容易让用户不知所措,让用户界面难以导航。

还要记住这些优化规则:

  1. 不要
  2. 说真的,不要。将硬件投入性能问题会更便宜,然后将您的代码优化到不再可维护的程度。
  3. 如果您认为必须,找到 1 瓶颈,使用分析工具并修复它。

关于java - Hibernate 中层次结构的高效表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2067297/

相关文章:

java - 从 Java 访问 OneNote API

java - 在给定的示例中,使用 Random 类背后的逻辑是什么?

java - 使用 envers 跟踪收视率

java - Spring boot 没有使用 spring 数据和 hibernate 与 sql server 一起运行

python - 单个表上的 SQLAlchemy 多对多关系

java - 如何在 Spring Boot 应用程序中将数据库架构更改从源数据库同步到目标数据库

java - PostgreSQL 函数不存在

sql - HQL:从 Eager 表中获取连接集合

java - 将带有 subselect in select 的 SQL 转换为 HQL

python - Tornado 的 ORM