@Transactional的自調用失效問題
有時候配置了注解@Transactional,但是它會失效,這里要注意一些細節問題,以避免落入陷阱。
注解@Transaction的底層實現是Spring AOP技術,而Spring AOP技術使用的是動態代理。這就意味着對於靜態(static)方法和非public方法,注解@Transactional是失效的。還有一個更為隱秘的,而且在使用過程中極其容易犯錯誤的——自調用。
所謂自調用,就是一個類的一個方法去調用自身另外一個方法的過程。
出現這個的問題根本原因在於AOP的實現原理。由於@Transactional的實現原理是AOP,而AOP的實現原理是動態代理,而自己調用自己的過程,並不存在代理對象的調用,這樣就不會產生AOP去為我們設置@Transactional配置的參數,這樣就出現了自調用注解失效的問題。
為了克服這個問題,一方面可以使用兩個服務類,Spring IoC容器中為你生成了RoleService的代理對象,這樣就可以使用AOP,且不會出現自調用的問題。另外一方面,你也可以直接從容器中獲取Service的代理對象,從IoC容器中獲取RoleService代理對象。但是有一個弊端,就是從容器獲取代理對象的方法有侵入之嫌,你的類需要依賴於Spring IoC容器
典型錯誤用法的剖析
數據事務是企業應用關注的核心內容,也是開發者最容易犯錯的問題,因此筆者在這里講解一些使用不良習慣,注意它們可以避免一些錯誤和性能的丟失。
錯誤使用Service
互聯網往往采用模型—視圖—控制器(Model View Controller,MVC)來搭建開發環境,因此在Controller中使用Service是十分常見的。
在Controller每調用一次帶事務的service都會創建數據庫事務。如果多次調用,則不在同一個事務中,這會造成不同時提交和回滾不一致的問題。每一個Java EE開發者都要注意這類問題,以避免一些不必要的錯誤。
過長時間占用事務
在企業的生產系統中,數據庫事務資源是最寶貴的資源之一,使用了數據庫事務之后,要及時釋放數據庫事務。換言之,我們應該盡可能地使用數據庫事務資源去完成所需工作,但是在一些工作中需要使用到文件、對外連接等操作,而這些操作往往會占用較長時間,針對這些,如果開發者不注意細節,就很容易出現系統宕機的問題。
一些系統之間的通信及一些可能需要花費較長時間的操作,都要注意這個問題,放在controller層等事務外進行處理,以避免長時間占用數據庫事務,導致系統性能的低下。
錯誤捕捉異常
帶事務的service中,出現異常想要回滾時應拋出異常,而不是捕獲