88

org.hibernate.Session.flush()单独打电话是个好习惯吗?

正如org.hibernate.Session文档中所说,

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

你能解释一下flush()明确调用的目的org.hibernate.Transaction.commit()吗?

4

7 回答 7

104

在 Hibernate Manual 你可以看到这个例子

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

你也可以看看这篇关于冲洗的帖子

于 2013-01-29T11:38:53.450 回答
92

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

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

于 2014-11-17T15:30:07.083 回答
57

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

另一种情况是,如果一级缓存中有很多东西,并且您想定期清除它(以减少缓存使用的内存量),但您仍然想将整个东西一起提交. 这就是阿列克谢的回答所涵盖的情况。

于 2013-01-29T14:37:50.253 回答
14

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

您需要在批处理中刷新,否则可能会出现 OutOfMemoryException。

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

于 2014-11-07T09:49:44.947 回答
8

通常不建议显式调用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());    
}

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

于 2017-11-21T13:24:06.230 回答
5

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

于 2013-01-29T11:39:40.300 回答
2

session.flush() 是同步方法,意思是按顺序向数据库中插入数据。如果我们使用这种方法,数据不会存储在数据库中,而是存储在缓存中,如果中间出现异常我们可以处理。但是 commit() 它将数据存储在数据库中,如果我们存储的数据量更大,那么可能会出现内存异常,就像保存点主题中的 JDBC 程序一样

于 2016-07-09T10:37:15.613 回答