Hibernate - 我真的需要回滚失败的只读事务吗?

时间:2014-12-10 14:06:34

标签: java hibernate rollback

我刚开始学习Hibernate,并且每次交易使用以下模式(来自documentation):

private Session session;
private Transaction transaction;

protected List selectAll(Class clazz) throws HibernateException {
    List objects = null;
    try {
        session = MyHibernateHelper.getSessionFactory().openSession();
        transaction = session.beginTransaction();

        // SELECT ALL
        objects = session.createCriteria(clazz).list();

        transaction.commit();
    } catch (HibernateException exc) {
        if (transaction != null) transaction.rollback();
        throw exc;
    } finally {
        session.close();
    }
    return objects;
}

我可以接受每个操作都应该包含在一个事务中。但是,如果它失败,我似乎很奇怪而且没有必要回滚select 我想我可以安全地删除上面示例中的catch块。从任何只读操作。我是对的吗?

2 个答案:

答案 0 :(得分:9)

考虑到Hibernate必须在各种情况下使用各种数据库。他们在文档中给出的是如何在任何支持的数据库中使用Hibernate。他们试图支持很多数据库。其中一些数据库可能会处理清理失败的事务而无需显式回滚,但Hibernate希望确保它涵盖所有人。

另外,考虑让只读事务失败在现实生活中极为罕见。一旦发生这种情况,回滚就不会有太大的作用,但是它做了什么 - 如Marc B指出的那样释放锁定 - 不是你想要跳过的东西。所以你所倡导的是一种非常微小的优化(根据路径的执行频率很少),在某些情况下会产生不良后果。锁定未被释放是一种不良后果,在其他事务失败或挂起之前不会显示,因此很难找到原因。锁未被释放可能会导致死锁,因此性能/可用性影响可能会很严重。这也是一个难以测试的问题,如果出现问题,在生产环境出现危机之前可能会错过。在多种情况下,这是你想要避免的事情。

这里最大的问题是每个交易都要包含很多样板代码。我的建议是使用回调或Command模式实现一些实用方法(参见Bauer和King的书籍Java Persistence with Hibernate),或采用框架。有一种反对框架的论点,它们掩盖了实施细节并使学习变得更加困难,但是你已经有了学习这些片段的经验。有成熟的框架,如SeamSpring,可以为您处理此问题。

答案 1 :(得分:1)

如果您使用的是框架或API,或者您实际上并不在您的控制之下,那么您应该始终尊重他们的失败策略,因为您不知道它的内部工作原理。可能还有其他资源可供免费使用。