Spring的事務(wù)實(shí)現(xiàn)采用基于AOP的攔截器來實(shí)現(xiàn),如果沒有在事務(wù)配置的時(shí)候注明回滾的checked exception,那么只有在發(fā)生了unchecked exception的時(shí)候,才會進(jìn)行事務(wù)回滾。因此在DAO層和service層,最好拋出unckecked exception,畢竟對于數(shù)據(jù)庫操作,使用unckecked exception更加合適,這個(gè)方面的例子hibernate就是一個(gè),在hibernate2中,HibernateException還是checked exceptions,但是到了hibernate3中就成了unchecked exceptions,因?yàn)閷τ跀?shù)據(jù)庫操作來說,一旦出現(xiàn)異常,就是比較嚴(yán)重的錯誤,而且在client端基本上是無能為力的,所以使用unchecked exceptions更加合適。
另外,在DAO和service層的代碼中,除非是為了異常的轉(zhuǎn)化、重新拋出,否則不要捕捉和處理異常,否則AOP在攔截的時(shí)候就不能捕捉到異常,也就不能正確執(zhí)行回滾。這一點(diǎn)通常很容易被忽視,只有在明白了spring的事務(wù)處理機(jī)制后,才能領(lǐng)會到。
對于hibernate的異常,spring會包裝hibernate的upckecked hibernateException到DAOAccessException,并且拋出,在事務(wù)管理層,一旦接收到DAOAccessException就會觸發(fā)事務(wù)的回滾,同時(shí)該異常會繼續(xù)向上層拋出,供上層進(jìn)一步處理,比如在UI層向用戶反饋錯誤信息等。
在spring的事務(wù)管理環(huán)境下,使用unckecked exception可以極大地簡化異常的處理,只需要在事務(wù)層聲明可能拋出的異常(這里的異??梢允亲远x的unckecked exception體系),在所有的中間層都只是需要簡單throws即可,不需要捕捉和處理,直接到最高層,比如UI層再進(jìn)行異常的捕捉和處理。