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

naX*_*aXa 11 java hibernate rollback

我刚刚开始学习Hibernate,并且我为每个事务使用以下模式(来自文档):

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

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

Nat*_*hes 9

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

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

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