Java 使用hibernate以树形结构加载非常大的数据并对它们进行分组

Java 使用hibernate以树形结构加载非常大的数据并对它们进行分组,java,hibernate,jpa,oracle11g,tree,Java,Hibernate,Jpa,Oracle11g,Tree,我有一个存储在oracle表中的非常大的数据集的树结构,在加载数据时,我得到java.lang.OutOfMemoryError。以下是完整的场景: 存储在Db表“Tree_hierarchy”中的树层次结构 树层次结构表数据: Id Node_Name Parent_Id 1 A 2 B 1 3 C 1 4 D 2 5 E 2 Id节点\u名称父节点\u Id 1A 2

我有一个存储在oracle表中的非常大的数据集的树结构,在加载数据时,我得到java.lang.OutOfMemoryError。以下是完整的场景:

存储在Db表“Tree_hierarchy”中的树层次结构

树层次结构表数据:

Id Node_Name Parent_Id 1 A 2 B 1 3 C 1 4 D 2 5 E 2 Id节点\u名称父节点\u Id 1A 2 B 1 3 C 1 4D2 5 E 2 每个节点(A、B、C等)至少包含20000条记录,最多可以增加到50000条记录。这些记录存储在单独的表“Tree_Data”中。因此,Tree_数据表包含来自每个节点的所有记录信息。此外,树层次结构/级别可以增长到30个级别。树层次结构和树数据都是JPA实体

树形图数据表结构:

Id Node_Name Column1, Column2, Column3,.........,Column70 1 A dataA11, dataA21, data13,........., data170 2 A dataA21, dataA22, data23,........., data270 ... 30001 B dataA11, dataA21, data33,........., data370 30002 B dataA21, dataA22, data43,........., data470 ... 60001 C dataA11, dataA21, data53,........., data570 ... 90001 D dataA11, dataA21, data63,........., data670 ... 120001 E dataA11, dataA21, data73,........., data770 Id节点名称Column1、Column2、Column3、…、Column70 1 A数据A11、数据A21、数据13、数据170 2 A数据A21、数据A22、数据23、…、数据270 ... 30001 B数据A11、数据A21、数据33、数据370 30002 B数据A21、数据A22、数据43、数据470 ... 60001 C数据A11、数据A21、数据53、…、数据570 ... 90001 D数据A11、数据A21、数据63、数据670 ... 120001 E数据A11、数据A21、数据73、数据770 问题陈述:
我必须将树层次结构中的所有节点以及Column1、Column2中的相同数据分组到一个“映射”中,键为ID_NodeName_Column1\u Column2,然后对数据执行一些分析。 因此,对于上面的三级树结构,地图中有30000个条目/组,列表包含5个元素(每个元素来自A、B、C、D、E)

当前情景: 目前我已经做到了这一点:首先我将树结构加载到列表中,然后将所有节点的所有数据加载到内存中(这意味着我将30000*5=150000 jpa实体加载到内存中),然后使用Java8流对这些数据进行分组

问题: 上面提到的单请求场景在4Gb的堆大小(仅在树级别5)下运行良好,但一旦出现第二个请求,就会遇到java.lang.OutOfMemoryError。我知道将如此大的对象加载到内存中是疯狂的,即使是16Gb的堆大小也无法在树级别为38的情况下工作

作为替代解决方案,我尝试从db本身加载分组数据。谁能为我提供从db加载分组数据的解决方案,或者建议其他方法


提前感谢。

您肯定不需要将所有数据加载到内存中。相反,定义分页逻辑以加载例如100条记录。加

criteria.setFirstResult()
criteria.setMaxResults()
加载前100条记录,处理它们,然后加载下100条。继续,直到处理完所有记录


更好的是,您可以同时加载和处理多个页面,并使用并行流进行分组。

感谢Stanislavl的回复。但我可以用第一个结果和最大结果。因为我必须对树层次结构进行分析。如果加载前100个结果,则可能无法执行分析/计算。对我来说,两种解决方案都是加载完整的数据并将其分组,然后执行分析/计算,或者直接从数据库获取分组数据。为什么需要加载所有这些数据?在计算分组数据时,无论如何都要以循环的方式遍历数据,例如,对它们进行计数。首先计算100,然后用计算值计算第二个。您将拥有从第一页到最后一页的循环以及每个页面的内部循环,而不是一个大循环。当然,您可以在Java8的流上组织它
criteria.setFirstResult()
criteria.setMaxResults()