Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java session.flush如何帮助内存释放?_Java_Database_Hibernate - Fatal编程技术网

Java session.flush如何帮助内存释放?

Java session.flush如何帮助内存释放?,java,database,hibernate,Java,Database,Hibernate,如java中所述 刷新是同步底层持久化进程的过程 存储在内存中的持久状态 以下是我对上述声明的理解 所以如果有人在做 插入/更新,然后刷新,额外插入的行将被放置 仅在java内存中。但另一种方法,即Db数据将仅限于 仅在提交时与内存中保持的持久状态同步 现在让我们从以上理解中走出来 我遇到了一个恰当的答案 在某些情况下,session.flush有助于释放内存,从而避免OutOfMemoryException 当我执行以下操作时,line1(session.flush())将对customer表

如java中所述

刷新是同步底层持久化进程的过程 存储在内存中的持久状态

以下是我对上述声明的理解

所以如果有人在做 插入/更新,然后刷新,额外插入的行将被放置 仅在java内存中。但另一种方法,即Db数据将仅限于 仅在提交时与内存中保持的持久状态同步

现在让我们从以上理解中走出来

我遇到了一个恰当的答案 在某些情况下,session.flush有助于释放内存,从而避免OutOfMemoryException

当我执行以下操作时,line1(session.flush())将对customer表上的20个客户执行insert查询 释放列表中20个客户对象的内存,但另一方面创建20个客户数据行 在仍然在java内存中的customer表下(它将仅在第2行提交时进入数据库)。所以我不确定 session.flush如何帮助释放内存

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