如何正确地捕获、包装和重新抛出 Hibernate 异常?

3

我的数据库工作是在Hibernate之上实现的。如果发生错误,它的方法应该回滚事务并抛出SQLException。所以我的问题是:处理Hibernate异常的最佳(即最干净)方法是什么?目前,我所有的方法看起来都像这样丑陋:

public EntryUserHib addUser(final String username, final String pwdhash) throws SQLException{
    try {
        final Transaction ta = sess.beginTransaction();
        try {
            // Using Hibernate here
            // "return" statement
        } catch(final HibernateException ex) {
            try {
                ta.rollback();
            } catch(final Exception ex1) {}
            throw ex;
        } finally {
            if (!ta.wasRolledBack()) ta.commit();
        }
    } catch(final HibernateException ex) {
        if (ex.getCause() != null) {
            if (ex.getCause() instanceof SQLException) throw (SQLException)ex.getCause();
            throw new SQLException(ex.getCause());
        }
        throw new SQLException(ex);
    }
}
2个回答

3
不要完全捕获它们。Hibernate异常继承RuntimeException有两个很好的理由:您不必在方法签名中声明它们,并且任何RuntimeException都会自动导致事务回滚。异常处理会使代码变得非常混乱。Hibernate开发人员的哲学是,HibernateExceptions应该是致命错误,表示编码或逻辑错误,并且在一个正常运行的应用程序中不应该被(也不需要被)捕获。
但是,您的应用程序UI应以用户友好的方式响应这些意外情况。那是另一个问题。

这是一个没有用户界面的服务器应用程序,有许多并行任务正在运行,而且其中任何一个都不应该对整个应用程序造成伤害,因此我真的需要以声明的方式捕获它们并重新抛出。另一个原因是,我的DatabaseWorker有三种实现方式 - 使用Hibernate、JDBC和简单的内存模型进行测试,目前我可以自由切换它们。 - Alex Abdugafarov
HibernateException包装了许多其他异常,包括SQLException,这可能是网络故障,不一定是编码或逻辑问题,具体是否致命取决于您的应用程序。在服务器情况下,HibernateException通常没有什么“致命”的地方,它通常应该被捕获并处理,服务器应该继续运行。 - teknopaul

2

2
谢谢,我会考虑的,但是仅仅为了一个单一类别的异常管理,我真的需要使用框架吗? - Alex Abdugafarov
1
一个普遍的误解是Spring仅仅是一个框架。它内置了大量可重用的库。例如,对于你的情况,它提供了一个TransactionTemplate和一个HibernateTemplate(如上所述),它们正好可以满足你的需求。是的,你可以自己编写它们,但为什么呢? - Ryan Stewart

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