我正在开发一个大型ERP项目,该项目拥有大约2100个表的数据库模型。仅使用""使用Hibernate映射的500个表,部署在Web服务器上的应用程序需要大约3GB的工作内存。
在一个持久性单元中使用那么多表时,有没有办法减少Hibernate的元模型内存占用?或者我应该放弃ORM并使用普通的旧JDBC(甚至是jOOQ)?
现在我正在使用Hibernate 4.1.8,Spring 3.1.3,JBoss AS 7.1并使用MSSQL数据库。
编辑:
JavaMelody memory histogram output - 使用2000个生成的测试表,这些测试表的范围比原始数据库模型小一点(因此仅消耗了1.3GB的内存)
编辑2:
Java MAT堆分析:
答案 0 :(得分:5)
打开的hibernate会话会在使用时产生对象。这不是内存泄漏; hibernate会话被设计为对请求使用一次,并且它缓存持久(即在会话中生活)的对象,以及查询和其他数据。如果您致电session.toString()
,您将看到会话中存在的对象清单。
如果使用大量对象,请考虑批量处理对象。您可以在每个批处理之后调用session.clear()
以从会话中逐出缓存数据和持久对象,并减少会话的内存占用(有时会非常显着)。
调用session.clear()
后,请注意在此调用之前加载的对象将恢复为分离的状态,并且不再对当前会话有效。
您还可以使用延迟提取来优化hibernate必须加载的数据量,以便处理给定的操作。您可以在hibernate文档中阅读更多相关信息。我建议启用hibernate的SQL日志记录功能,并检查hibernate是否正在撤回它不需要的数据。
您还可以配置hibernate以收集可以帮助您的统计信息:
sessionFactory.getStatistics().setStatisticsEnabled(true);
答案 1 :(得分:4)
我建议使用java melody分析生产中的应用程序或使用{{3}}进行分段,以找出消耗最大内存的位置或者谁,并根据分析结果,您应该决定应用程序应该进行哪些更改。
Java melody非常易于集成和配置,在生产中,您只需更新web.xml即可启用或禁用
答案 2 :(得分:2)
我重写了同样的问题,并且我成功地将内存消耗从xGB减少到30M,buildSessionFactory从2分钟传递到7个secondes。
解决方案的一个重要部分发布在这里
postInstantiate buildSessionFactory slow/memory huge database
答案 3 :(得分:1)
你的hibernate对象的目的是什么,hibernate只适用于CURD(创建,更新,读取,删除),但不适合计算。对于任何计算目的(特别是交叉表),使用存储过程和ibatis一起更好。