如果在Hibernate中不回滚事务会发生什么?

9

关于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呢?


3
谁告诉你Hibernate会让事情变得简单? :) - skaffman
2个回答

5
Hibernate可以让很多事情变得更简单,但是事务管理并不是很简单,因此对于每个事务,您都必须仔细考虑您想要的内容。Hibernate无法帮助您解决这个问题。
如果try块中的代码抛出除RuntimeException之外的任何异常,则您的事务显然不会提交。但是您也没有显式回滚。finally块中的sess.Close调用也不会回滚事务。发生的情况取决于这是否是嵌套事务:
- 如果不是,则最终事务超时并回滚。 - 如果是,则父事务将看到子事务未提交而自身提交。这将导致整个事务回滚。

0
更重要的是,如果try块中的代码抛出除RuntimeException之外的其他异常会发生什么?
如果在try块中的代码块中可能出现除RuntimeException之外的任何其他异常,那么这将是一个已检查的异常,编译器本身将捕获它,并且您将最终在代码中包含处理部分。
在此问题提供的示例中,我们仅捕获RuntimeException,我认为这是正确的编码方式。通过这样做,我们可以立即回滚事务,而无需等待事务超时和最终回滚。由于我们继续重新抛出RuntimeException,因此我们也没有破坏异常流。这比让事务超时触发事务回滚更清洁和更明确地处理事务的方式。
当然,出于明显的原因,我们不应该像捕获RuntimeException一样捕获“Exception”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接