如果你不在Hibernate中回滚事务会怎么样?

时间:2010-08-27 20:52:49

标签: java hibernate orm transactions rollback

我读到的关于Hibernate的所有内容都表明你必须回滚事务并在发生错误时关闭会话,并且通常会给出以下代码的一些变体(取自Hibernate的文档)作为示例:

Session sess = factory.openSession();
Transaction tx = null;
try {
    tx = sess.beginTransaction();
    // do some work
    ...
    tx.commit();
} catch (RuntimeException e) {
    if (tx != null) tx.rollback();
    throw e; // or display error message
} finally {
    sess.close();
}

由于几个原因,这种模式对我来说似乎很奇怪。首先,对于一个通常用于简化事物的框架来说,这似乎是不合理的复杂。更重要的是,如果try块中的代码抛出RuntimeException之外的其他内容会发生什么?在这种情况下,Hibernate看起来好像必须能够通过打开事务优雅地关闭会话,大概是通过回滚它,但如果这是真的,为什么还要打扰rollback呢?

2 个答案:

答案 0 :(得分:4)

Hibernate可能会使很多事情变得更简单,但事务管理并不是很简单,因此对于每个事务,您必须非常仔细地考虑您想要的事情。 Hibernate无法帮助你。

如果try块中的代码抛出除RuntimeException以外的任何内容,则您的事务显然不会提交。但是你也没有显式回滚。 sess.Close阻止中的finally调用也不会回滚事务。会发生什么取决于这是否是嵌套事务:

  • 如果不是,则最终交易超时并回滚。
  • 如果是,父事务将在提交时看到子事务未提交。这将导致整个事务的回滚。

答案 1 :(得分:0)

  

更重要的是,如果try块中的代码抛出会发生什么   除了RuntimeException以外的东西?

如果除了RuntimeException之外,try块中的代码块中可能存在任何其他异常,则必须是一个已检查的异常,它将被编译器本身捕获,并且最终会合并处理部分在你的代码中。

在这个问题中提供的示例中,我们只捕获RuntimeException,我觉得这是正确的代码方式。通过这样做,我们可以直接回滚事务,而无需等待事务超时和最终回滚。当我们继续重新抛出RuntimeException时,我们也没有打破异常流。这比使事务超时触发事务回滚更清晰,更明确地处理事务。

当然,我们不应该抓住'例外'因为显而易见的原因,正在捕获RuntimeException。