Java 大事务中间安全休眠会话的安全清除
我正在使用Spring+Hibernate进行一项操作,该操作需要创建和更新成百上千个条目。大概是这样的:Java 大事务中间安全休眠会话的安全清除,java,hibernate,spring,orm,Java,Hibernate,Spring,Orm,我正在使用Spring+Hibernate进行一项操作,该操作需要创建和更新成百上千个条目。大概是这样的: { ... Foo foo = fooDAO.get(...); for (int i=0; i<500000; i++) { Bar bar = barDAO.load(i); if (bar.needsModification() && foo.foo()) { bar.setWhatever("new
{
...
Foo foo = fooDAO.get(...);
for (int i=0; i<500000; i++) {
Bar bar = barDAO.load(i);
if (bar.needsModification() && foo.foo()) {
bar.setWhatever("new whatever");
barDAO.update(bar);
// commit here
Baz baz = new Baz();
bazDAO.create(baz);
// if (i % 100 == 0), clear
}
}
}
在这一点上,我必须说,整个流程都在一个事务中运行,该事务被包装到org.springframework.orm.hibernate3.support.ExtendedOpenSessionInViewFilter
(是的,这是一个webapp)
这一切都很好,只有一个例外:在几千次更新/提交之后,整个过程变得非常缓慢,很可能是由于Spring/Hibernate保存的对象数量不断增加而导致内存膨胀
在只有Hibernate的环境中,通过调用org.Hibernate.Session#clear()
可以很容易地解决这个问题
现在,问题是:
- 什么时候是清除()的好时机?它的性能成本大吗
- 为什么像
或bar
这样的对象不能自动释放/GCd?在提交之后将它们保留在会话中有什么意义(在迭代的下一个循环中,它们无论如何都无法访问)?我还没有做内存转储来证明这一点,但我的好感觉是,它们仍然存在,直到完全退出。如果答案是“Hibernate cache”,那么为什么可用内存不足时缓存没有刷新baz
- 直接调用
是否安全/推荐(记住整个Spring上下文,比如延迟加载等)?是否有任何可用的Spring包装器/对应物来实现相同的功能org.hibernate.Session#clear()
- 如果上述问题的答案为真,那么假设在循环中调用了
,那么对象clear()
会发生什么情况?如果foo
foo.foo()
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) { //20, same as the JDBC batch size
//flush a batch of inserts and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
Session Session=sessionFactory.openSession();
事务tx=会话.beginTransaction();
对于(int i=0;i我只想指出,在清除会话后,如果您想继续使用会话中的某些对象,您必须session.refresh(obj)
它们才能继续
否则将出现以下错误:
org.hibernate.NonUniqueObjectException
感谢您澄清这个Pascal!我也在做多个大的插入。偶尔添加代码刷新和清除会话只会使我的代码运行快4倍!请在回答中用“`为了更好的可读性-session.refresh(obj)
org.hibernate.NonUniqueObjectException