HIbernate commit()和flush()

时间:2013-01-29 11:29:05

标签: java hibernate orm

我搜索了很多,并且大量阅读org.hibernate.Transaction.commit()org.hibernate.Session.flush(),了解每种方法的目的,但仍有疑问。

手动调用org.hibernate.Session.flush()方法是一种好习惯吗?如org.hibernate.Session文档中所述,

  

必须在提交事务并关闭会话之前在工作单元结束时调用(取决于flush模式,Transaction.commit()调用此方法)。

如果org.hibernate.Session.flush()自动调用它,您能解释一下我手动拨打org.hibernate.Transaction.commit()的目的吗?

谢谢!

7 个答案:

答案 0 :(得分:81)

在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

答案 1 :(得分:55)

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

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

答案 2 :(得分:45)

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

另一种情况是,如果第一级缓存中有很多内容,并且您希望定期清除它(为了减少缓存使用的内存量),但您仍然希望提交整个事情在一起。这是Aleksei's answer涵盖的情况(+1来自我)。

答案 3 :(得分:11)

flush(); 刷新是将底层持久存储与内存中保存的持久状态同步的过程。它将在正在运行的事务中更新或插入到表中,但它可能不提交那些变化。

  

您需要在批处理中进行刷新,否则可能会给出   的 OutOfMemoryException异常。

提交(); 提交将使数据库提交。当你有一个持久化对象并且你在其上更改一个值时,它就变脏了,而且hibernate需要将这些更改刷新到你的持久层。所以你应该提交,但它也结束了工作单元。 transaction.commit()

答案 4 :(得分:5)

除非有必要,否则通常不建议明确调用flush。 Hibernate通常在事务结束时自动调用Flush,我们应该让它做它的工作。现在,在某些情况下,您可能需要显式调用flush,而第二个任务依赖于第一个Persistence任务的结果,两者都在同一个事务中。

例如,您可能需要持久保存新实体,然后使用该实体的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后发生任何运行时错误,则更改仍将是Rollback。

答案 5 :(得分:3)

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

答案 6 :(得分:2)

session.flush()是同步方法,意味着将数据顺序插入到数据库中。如果我们使用这种方法,数据将不会存储在数据库中,但它会存储在缓存中,如果有任何异常将在中间上升,我们可以处理它。 但是commit()它会将数据存储在数据库中,如果我们存储的数据量更多,那么可能会有机会退出内存异常,就像保存点主题中的JDBC程序一样