从Spring和Hibernate的设计来理解合理的异常处理体系

 

关于在应用程序中如何设计合理的异常体系,在《深入浅出Hibernate》这本书中有一大段详细的论述,另外一些JAVA界的高人也先后发表过专门的文章来讨论这个问题,书中也给出的文章的链接。 

其实,通过Hibernate和Spring中对异常处理的态度,就可以看出一些好的设计原则。在Hibernate2的时候,调用Hibernate的API时必须处理一个CheckedException,这和使用JDBC时是一样的,Hibernate的作者在后来的一封Email中也承认多少是受了JDBC的影响。但是面对这种底层的异常,我们能做些什么呢?继续抛上去或者捕获后什么都不做。这样的做法只能使程序中充满了重复的没有太大意义的try...catch...代码,而其功能和一个UncheckedException没用太大差别。所以Spring包装了Hibernate后抛出了一个UnckeckedException。后来Hibernate也意识到抛出一个UncheckedException是一种更合适的做法,所以在Hibernate3中不再抛出CheckedException了。 

今天又看到了一个Spring的特性,更加说明了Spring在异常处理方面的思路和态度: 

默认的情况下,spring只有当unchecked exception被抛出时,才rollback事务。 
<property name="transactionAttributes">   
    <props>   
            <prop key="insert*">PROPAGATION_REQUIRED,- MyCheckedException,+MyUnCheckedException</prop>   
            <prop key="update*">PROPAGATION_REQUIRED</prop>   
            <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>   
        </props>   
</property>   
-MyCheckedException 指定如果方法抛出MyCheckedException或它的子类,事务将 会自动回滚。 
+MyUnCheckedException 指定如果方法抛出MyUnCheckedException或它的子类,事务仍将会提交。 

可我们的项目中是怎么做的呢? 

几乎在每一层的每一个方法中都try...catch一下,然后在catch代码块中抛出一个OAException,这个OAException是New出来的而且还是一个CheckedException,包含了一句简单的异常信息,如“数据访问出现错误……”。这样做的后果有两个,一是又回到了Hibernate2的那种异常处理方式,使代码变的复杂了,有时候只有一两行的代码就可以搞定的现在要写个十多行的异常处理代码。二是丢掉了原始的异常信息,这一点就更严重了,由于OAException是New出来的,所以只包含了简单的提示信息,而真正出现异常的原始信息却丢掉了。另外,从上面Spring事务的回滚机制来看,如果采用默认配置,事务都会变的形同虚设了。 

这种异常处理体系对程序员是一种痛苦,对程序设计来说是一种缺憾! 

相关推荐