HIbernate commit()和flush()

bsi*_*nau 70 java orm hibernate

我用Google搜索了很多,了解org.hibernate.Session.flush()org.hibernate.Session不少,知道每种方法的目的,但仍然有一个问题.

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

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

org.hibernate.Session.flush()如果org.hibernate.Session能自动调用,你能解释一下手工打电话的目的吗?

谢谢!

Ale*_*gak 87

在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();
Run Code Online (Sandbox Code Playgroud)

如果不调用flush方法,您的第一级缓存将抛出OutOfMemoryException

你也可以看看关于潮红的这篇文章

  • 这个答案给出了一个特定的情况,其中明确地调用flush是一个好主意,但我不认为它解决了是否应该总是这样做的一般问题. (3认同)

小智 62

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

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


Nat*_*hes 49

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

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


Ash*_*shu 12

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

您需要在批处理中进行刷新,否则可能会产生 OutOfMemoryException.

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


adn*_*911 6

除非有必要,否则通常不建议明确调用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());    
}
Run Code Online (Sandbox Code Playgroud)

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


dim*_*mas 5

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