Java session.flush如何帮助内存释放?
如java中所述 刷新是同步底层持久化进程的过程 存储在内存中的持久状态 以下是我对上述声明的理解 所以如果有人在做 插入/更新,然后刷新,额外插入的行将被放置 仅在java内存中。但另一种方法,即Db数据将仅限于 仅在提交时与内存中保持的持久状态同步 现在让我们从以上理解中走出来 我遇到了一个恰当的答案 在某些情况下,session.flush有助于释放内存,从而避免OutOfMemoryException 当我执行以下操作时,line1(session.flush())将对customer表上的20个客户执行insert查询 释放列表中20个客户对象的内存,但另一方面创建20个客户数据行 在仍然在java内存中的customer表下(它将仅在第2行提交时进入数据库)。所以我不确定 session.flush如何帮助释放内存Java session.flush如何帮助内存释放?,java,database,hibernate,Java,Database,Hibernate,如java中所述 刷新是同步底层持久化进程的过程 存储在内存中的持久状态 以下是我对上述声明的理解 所以如果有人在做 插入/更新,然后刷新,额外插入的行将被放置 仅在java内存中。但另一种方法,即Db数据将仅限于 仅在提交时与内存中保持的持久状态同步 现在让我们从以上理解中走出来 我遇到了一个恰当的答案 在某些情况下,session.flush有助于释放内存,从而避免OutOfMemoryException 当我执行以下操作时,line1(session.flush())将对customer表
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(); //line1
session.clear();
}
}
tx.commit();// line2
session.close();
Session Session=sessionFactory.openSession();
事务tx=会话.beginTransaction();
for(int i=0;iflush()将数据发送到数据库。您将看到,如果在Hibernate中激活SQL日志记录,则提交()将提交以前发送到数据库的更改。可能是缓存保留了所有或部分数据。在这种情况下,您必须调整缓存设置
也就是说,如果内存中有太多已更改或新对象,需要进行刷新以避免OutOfmemoryError,那么很可能需要在更深层次上更改设计,例如进行多个但较小的事务。如此大的事务可能会给应用程序和数据库带来问题。原料药
强制此会话刷新。必须在一个会话单元结束时调用
在提交事务和关闭会话之前进行工作
(根据刷新模式,Transaction.commit()调用此方法)
刷新是同步底层持久化进程的过程
存储在内存中的持久状态
所以,这种方法的目的是将您的持久状态与底层数据库同步。若您仍然有对对象的引用,那个么它将无助于释放内存
另请参阅此链接-
在程序中,您在for loop
内部创建100000
Customer
。如果没有hibernate代码,则表示您没有维护这些对象的任何引用,因此它们符合垃圾收集的条件
但是当你说session.save(customer)
时,对象与Hibernate的会话相关联,因此它们将被放置在一级缓存中
如果对象数量增加,并且没有足够的内存可用,那么当hibernate试图在内存中维护所有这些对象时,就会出现内存不足的问题。因此,调用flush
方法将使hibernate调用数据库所需的查询,调用clear
将有助于它在第一级释放内存l缓存从而释放一些内存
更新:
调用session.clear()
调用它调用的位置和其他对象。这会清除一级缓存中的内存。这清楚地表明对象有资格进行垃圾收集,这有助于释放一些内存。因此该状态不再由Hibernate维护,因此对象处于分离状态
现在根据API:
刷新相关会话并结束工作单元(除非
在FlushMode.MANUAL中
当且仅当
此对象已启动基础事务
调用commit()
刷新所有挂起的项,然后向基础数据库发出commit
更新:
另请参阅此链接-,其中明确指出,JDBC调用是在调用flush()
方法时进行的
有时,会话将执行所需的SQL语句
将JDBC连接的状态与保留对象的状态同步
在内存中。这个过程称为刷新
除非显式刷新(),否则绝对没有任何保证
关于会话何时执行JDBC调用,只有
他们被处决了
@MSach,用更多细节更新了我的答案,请检查这是否有帮助。你说“flush方法将使hibernate调用对数据库的所需查询”。这就是我怀疑的。它不会调用对物理数据库的所需查询,而是对数据库表的所需查询(持久状态)保留在java内存中。@MSach,我想这是不对的,我认为查询是从我看到的日志中发送到DB的。甚至API都说刷新是将底层持久存储与内存中的持久状态同步的过程。
这里持久存储代表的是数据库而不是内存。一旦调用清除则对象不再在内存中。您能否提供一些支持您的语句的链接。您的意思是说flush使查询针对DB触发(内部意味着DB会话将其保留在某个位置),并且在提交时,其实际已提交。@MSach,是的,提交就是提交事务。session.clear()
是清除内存的实际对象,请参阅StatefulPersistenceContext.clear()
(在我的回答中)的链接。在那里,您可以清楚地看到,通过清除各种对象可以释放内存,其中一些对象是Map的
void flush()
throws HibernateException
void commit()
throws HibernateException