休眠:flush()和commit()

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了休眠:flush()和commit()相关的知识,希望对你有一定的参考价值。

分别调用org.hibernate.Session.flush()是一种好习惯吗?

org.hibernate.Session文档中所述,

在提交事务并关闭会话之前,必须在工作单元的末尾调用(取决于刷新模式,Transaction.commit()会调用此方法)。

如果flush()已经执行,您能否明确说明调用org.hibernate.Transaction.commit()的目的?

答案

在Hibernate手册中,您可以看到此示例

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();

没有对flush方法的调用,您的一级缓存将抛出OutOfMemoryException

Also you can look at this post about flushing

另一答案

flush()会将数据库与内存中保存的一个或多个对象的当前状态同步,但不提交事务。因此,如果在调用flush()之后收到任何异常,则事务将回滚。您可以使用flush()将数据库与小块数据同步,而不是使用commit()一次提交大数据,并且面临获得OutOfMemoryException的风险。

commit()将使数据库中存储的数据永久存在。 commit()成功后,您将无法回滚事务。

另一答案

显式刷新的一种常见情况是,当您创建一个新的持久性实体并希望它为它生成并分配了一个人工主键,以便以后可以在同一事务中使用它时。在这种情况下,调用flush将导致为您的实体提供一个ID。

[另一种情况是,如果一级缓存中有很多东西,并且您想定期清除它(以减少缓存使用的内存量),但是您仍然想提交全部内容在一起。 Aleksei's answer属于这种情况。

另一答案

[flush();刷新是将基础持久性存储与保存在内存中的可持久性状态进行同步的过程。它会在正在运行的事务中更新或插入到您的表中,但可能不会提交这些更改。

您需要在批处理中冲洗,否则可能会导致OutOfMemoryException。

[Commit();提交将使数据库提交。当您拥有一个持久对象并在其上更改值时,该对象将变脏,并且休眠状态需要将这些更改刷新到持久层。因此,您应该提交但也要结束工作单元(transaction.commit())。

另一答案

除非有必要,通常不建议显式调用冲洗。 Hibernate通常在事务结束时自动调用Flush,我们应该让它完成工作。现在,在某些情况下,您可能需要显式调用冲洗,其中第二个任务取决于第一个持久性任务的结果,它们都在同一个事务中。

例如,您可能需要保留一个新实体,然后使用该实体的ID在同一事务内执行其他任务,在这种情况下,需要先显式刷新该实体。

@Transactional
void someServiceMethod(Entity entity){
    em.persist(entity); 
    em.flush() //need to explicitly flush in order to use id in next statement
    doSomeThingElse(entity.getId());    
}

还请注意,显式刷新不会导致数据库提交,数据库提交只会在事务结束时完成,因此,如果在调用flush之后发生任何运行时错误,则更改仍会回滚。

另一答案

默认情况下,刷新模式为AUTO,这意味着:“有时会在查询执行前刷新会话,以确保查询不会返回陈旧状态”,但是大多数时间,在提交更改时会刷新会话。当您使用FlushMode = MANUAL或想要进行某种优化时,手动调用flush方法非常有用。但是我从来没有做过,所以我不能给你实际的建议。

另一答案

session.flush()是synchronize方法,是指将数据顺序插入数据库中。如果使用此方法,数据将不会存储在数据库中,但会存储在缓存中,如果中间出现任何异常,我们可以处理。但是commit()会将数据存储在数据库中,如果那么我们要存储更多的数据,则可能有机会摆脱内存异常,就像在JDBC程序中的保存点主题

以上是关于休眠:flush()和commit()的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy:flush() 和 commit() 有啥区别?

Hibernate commit() 和flush() 的区别

MySQL参数:innodb_flush_log_at_trx_commit 和 sync_binlog

MySQL参数:innodb_flush_log_at_trx_commit 和 sync_binlog

Lucene中的IndexWriter的commit和flush之间有什么区别

innodb_flush_log_at_trx_commit 和sync_binlog介绍