使用OpenSessionInView的Hibernate Cache1 OutOfMemory

时间:2011-01-21 12:03:57

标签: java hibernate profiling out-of-memory

我有一个车辆实体,带有车辆DTO。

我在条纹中使用OpenSessionInView

在我的Stripes动作bean中,我需要生成一个包含大约50000辆车的数据的csv。

因此,正如Stripes开发人员告诉我的那样,我用以下方法将文件写入输出流:

StreamingResolution() {...}.stream(HttpServletResponse)

我有一项服务,可以获取一些分页信息,加载一部分车辆并将其转换为DTO。

这些dto将返回到视图并写入csv。

分页系统(每页500个项目)是为了避免列出50000 DTO并出现内存问题。

但它还不完美。使用Jmap,我看到在csv进程结束时,堆空间中加载了超过40000个车辆,而不是垃圾回收。

使用Yourkit分析器,在我看来,这些实体仍然在休眠的L1缓存中(在StatefulPersistenceContext中引用),并且由于我有OpenSessionInView,我想问题是对话有点长,需要清理缓存......

我只是想知道如何以优雅的方式做到这一点,因为我的dao方法加载车辆被很多服务使用,不需要会话清理/冲洗。

有人知道我能做到吗?我想我可以在DAO / Service中创建一个方法来清除会话,但它不是很优雅......

这是一个非常大的项目,我对它进行了非常简单的描述。请不要告诉我不要使用opensessioninview或类似的东西,这不是我的决定......;)

3 个答案:

答案 0 :(得分:4)

它可能并不优雅,但在这样的情况下,会话中的驱逐实体是唯一可行的解​​决方案。

例如,一旦您将实体的数据写入输出流,请调用session.evict(entity)将其从会话缓存中删除。或者,在每个“页面”的末尾调用它。

分页机制和逐出的组合应确保您一次不会在缓存中拥有超过500个实体。

答案 1 :(得分:4)

驱逐对象 优雅,在执行报告,导出到CSV等时是唯一良好的解决方案。

最优雅的方法是在服务中实现它,它将打开迭代器,在处理后逐出每个项目。该类将用于服务调用,即项目消费者。

public interface ItemConsumer {   void consume(Item item); }

public void processAllItems(ItemConsumer consumer){

..做你的工作 }

答案 2 :(得分:3)

您可能希望明确打开无状态会话。

e.g。

StatelessSession session = sessionFactory.openStatelessSession();

来自文档:

  

StatelessSession没有持久性   与之相关的背景和确实如此   没有提供更多的更高层次   生命周期语义学。特别是,a   无状态会话没有实现   第一级缓存也不与之交互   任何二级或查询缓存。它   没有实现事务性   后写或自动脏   检查

请点击此处了解更多详情:

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/batch.html