org.hibernate.Session.flush()
单独打电话是个好习惯吗?
如org.hibernate.Session
文档中所述,
在提交事务并关闭会话之前,必须在工作单元的末尾调用(取决于刷新模式,Transaction.commit()调用此方法)。
您能解释一下flush()
是否org.hibernate.Transaction.commit()
会明确呼叫的目的吗?
org.hibernate.Session.flush()
单独打电话是个好习惯吗?
如org.hibernate.Session
文档中所述,
在提交事务并关闭会话之前,必须在工作单元的末尾调用(取决于刷新模式,Transaction.commit()调用此方法)。
您能解释一下flush()
是否org.hibernate.Transaction.commit()
会明确呼叫的目的吗?
Answers:
在《 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
flush()
将数据库与内存中保存的一个或多个对象的当前状态同步,但不提交事务。因此,如果在flush()
调用后收到任何异常,则事务将回滚。您可以使用flush()
来将数据库与小块数据同步,而不是使用一次提交大数据,否则会commit()
面临获取的风险OutOfMemoryException
。
commit()
将使存储在数据库中的数据永久保存。一旦commit()
成功,您将无法回滚事务。
显式刷新的一种常见情况是,当您创建一个新的持久性实体时,您希望它具有生成并分配给它的人工主键,以便以后可以在同一事务中使用它。在这种情况下,调用flush将导致为您的实体提供一个ID。
另一种情况是,如果一级缓存中有很多东西,而您想定期清除它(以减少缓存使用的内存量),但您仍然想将整个东西一起提交。Aleksei的答案就是这种情况。
.refresh(...)
除非必要,通常不建议显式调用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之后发生任何运行时错误,则更改仍会回滚。
sessionFactory
使用@Transactional
注解注入,如果您查看了注解。从此以后,您将不需要代码在任何地方都具有事务性(尽管在某些情况下需要这样做)。