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

时间:2015-12-28 10:27:53

标签: java hibernate jpa oracle11g tree

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

树层次结构存储在Db表" Tree_Hierarchy"

   A
  / \
 B   C
/ \
D   E       

Tree_Hierarchy表数据:

Id Node_Name   Parent_Id
1   A           
2   B           1
3   C           1
4   D           2
5   E           2

每个节点(A,B,C等)至少包含20,000条记录,最多可增加50,000条记录。这些记录存储在单独的表" Tree_Data"中。所以Tree_Data表包含来自每个节点的所有记录信息。树层次结构/级别也可以增长到30级。 Tree_Hierarchy和Tree_Data都是JPA实体

Tree_Data表结构:

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  

问题陈述:
我必须将树层次结构中的所有节点与Column1,Column2中的相同数据组合成" Map< Key,List< Tree_Data>>"使用key作为ID_NodeName_Column1_Column2,然后对数据执行一些分析。 因此,对于具有3个级别的上述树结构,Map中将有30000个条目/组,其中包含5个元素(每个元素来自A,B,C,D,E)。

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

问题: 上面提到的单个请求场景与4Gb的堆大小(仅与树级别5)一起工作正常,但是一旦第二个请求到来,就会遇到java.lang.OutOfMemoryError。我知道将这样一个大对象加载到内存中是疯狂的,甚至16Gb的堆大小也不适用于38级的树级。

作为替代解决方案,我试图从db本身加载分组数据。任何人都可以为我提供从db加载分组数据或建议任何其他方法的解决方案。

提前致谢。

1 个答案:

答案 0 :(得分:0)

您绝对不需要将所有数据都加载到内存中。而是定义要加载的分页逻辑100条记录。添加

criteria.setFirstResult()
criteria.setMaxResults()

加载前100条记录,处理它们并加载下一条100.继续直到处理完所有记录。

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