我提到了很多文章,但我仍然不清楚session.clear
在hibernate中的表现。
根据我目前所遇到的是, 当我们使用批量保存/更新时,如下所示:
Session session = SessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Employee employee = new Employee(.....);
session.save(employee);
if( i % 50 == 0 ) { // Same as the JDBC batch size
//flush a batch of inserts and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
sesion.flush();
用于刷新会话强制Hibernate将Session的内存状态与数据库同步。
问题
1。在刷新会话后,为什么需要session.clear()
?真的需要吗?
2。 session.clear()
会执行提交操作吗?
3. 如果session.clear()
驱逐所有已加载的对象,执行提交和回滚操作时内部会发生什么?
答案 0 :(得分:16)
将Session视为您已从(或保留)数据库加载的实体的缓存,因为您已启动当前事务。
Session.clear
在任何情况下都不是强制性的,但如果您在一个事务中执行大量实体加载/保存,则会很有用,以避免出现内存不足错误。在您的示例中,您将在会话中复制50个employee
个实体。如果没有flush
和clear
方法调用每50 save()
,您将在会话中复制100,000个实体(而不是垃圾收集,因为会话具有指向实体的链接)。 / p>
Session.clear
不会执行提交或回滚。甚至不是flush
(因此你应该在Session.clear
之前进行刷新,以便hibernate为未决实体更新生成sql查询。
回滚或提交操作不是在应用程序端执行,而是在数据库中执行:hibernate只会要求数据库提交或回滚(Hibernate可能会在提交操作之前触发刷新,但刷新不是提交)。提交操作不会(也不能)访问会话。它是一种数据库内部机制,它将持续(或恢复)所执行的数据修改,这要归功于自事务开始以来运行的所有SQL查询。
完全以同样的方式,在hibernate中打开一个事务并没有执行很多事情:主要是从池中获取数据库连接,并告诉数据库 NOT auto_commit
跟随sql查询但等待提交或回滚命令。
答案 1 :(得分:0)
Thierry 的回答非常好。但是如果客户端并发连接过多,内存问题(GC)。最好的解决方案是我在这里做的:不直接使用 mysql 或 postgres 的本机 JDBC 连接器进行休眠。