我有一个车辆实体,带有车辆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或类似的东西,这不是我的决定......;)
答案 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