Spring事務中的那些坑
專案已進展了很長時間,突然發現曾經配置過的事務居然不起作用.經專案同事一起努力,從配置到程式碼逐一進行排查,終於把這些坑給填上了.
1.Spring配置問題
為了省事,沒有采用註解的方式進行事務控制,即專案中的方法都不加@Transaction,而是配置了自動掃描相關包及方法的方式.
配置如下:
<aop:pointcut id="tms-allSysDaoMethod"
expression="execution(* com.######.#####.dao.*.*(..))" />
<aop:pointcut id="tms-allSysServiceMethod"
expression="execution(* com.######.#####.service.*.*(..))"/>
其中: #為了專案保密,省略部分名稱.
從配置資訊上看,並沒有什麼問題,然而,關鍵的地方在於配置的層級跟專案程式碼層級不匹配.Spring中的Aop事務配置,要求配置的路徑對映到具體的方法,即:service後的第一個*對映的應該是類名,第二個*對應的應該是具體的方法,(..)代表了方法的引數.
專案中,在service後依然是包名,即模組名,如:service.user,之後才是具體的類.這使得Spring根本無法掃描到要事務處理的方法.只需多加一層.*進行對應即解決問題.
2.業務程式碼問題
配置檔案問題解決後,依然發現有些模組事務仍然不起作用.這次的罪魁禍首是 try....catch.....
try...catch...的作用不用多解釋了,但是如果你不小心把大段的程式碼放置到try....catch...內部,問題可能就來了.這裡的關鍵是,操作資料庫的方法,如Mapper的方法的操作放在了try...catch...內部,你在try...catch...之前 或之後又有別的資料庫的操作,那麼這個時候,你就打破了事務的控制.
我們最終採用的方法時,把try....catch....放在控制器,service方法將事務往上拋.當然也可以對小範圍的程式碼實行try....catch.....,但一定不要包含到資料庫操作
總結:
1.錯誤認識:以為Spring可以掃描到具體的包,自動控制該包以下所有層級的類和方法事務.
2.業務程式碼中,try...catch...使用時,為認真檢查包含的範圍.