@Transactional 注解
@Transactional 是聲明式事務管理 編程中使用的注解
添加位置
@Override @Transactional public void upd(Stu stu) { }
接口實現類或接口實現方法上,而不是接口類中
訪問權限:public 的方法才起作用
@Transactional 注解應該只被應用到 public 方法上,這是由 Spring AOP 的本質決定的。如果你在 protected、private 或者默認可見性的方法上使用 @Transactional 注解
系統設計:將標簽放置在需要進行事務管理的方法上,而不是不假思索的放置在接口實現類上( 接口中所有方法都需要進行事務管理,但其實並不需要,如只讀的接口就不需要事務管理,但是 由於配置了@Transactional就需要AOP攔截及事務的處理,影響系統性能)
方法上注解屬性會覆蓋類注解上的相同屬性,當接口與接口中方法上同時帶有@Transactional注解時
錯誤使用:
接口中A、B兩個方法,A無@Transactional標簽,B有,上層通過A間接調用B,此時事務不生效
接口中異常(運行時異常)被捕獲而沒有被拋出
默認配置下,spring只有在拋出的異常為運行時unchecked異常時才回滾該事務,也就是拋出的異常為RuntimeException的子類(Errors也會導致事務回滾),而拋出checked異常則不會導致事務回滾
可通過 @Transactional rollbackFor進行配置
多線程下事務管理
因為線程不屬於spring托管,故線程不能夠默認使用spring的事務,也不能獲取spring注入的bean
在被spring聲明式事務管理的方法內開啟多線程,多線程內的方法不被事務控制
一個使用了@Transactional 的方法,如果方法內包含多線程的使用,方法內部出現異常,不會回滾線程中調用方法的事務
基於@Transactional注解
@Transactional實質是使用了JDBC的事務來進行事務控制的
@Transactional基於Spring的動態代理的機制
@Transactional實現原理
1)事務開始時,通過AOP機制,生成一個代理connection對象,並將其放入DataSource實例的某個與DataSourceTransactionManager相關的某處容器中。在接下來的整個事務中,客戶代碼都應該使用該connection連接數據庫,執行所有數據庫命令[不使用該connection連接數據庫執行的數據庫命令,在本事務回滾的時候得不到回滾](物理連接connection邏輯上新建一個會話session;DataSource與TransactionManager配置相同的數據源)
2)事務結束時,回滾在第1步驟中得到的代理connection對象上執行的數據庫命令,然后關閉該代理connection對象(事務結束后,回滾操作不會對已執行完畢的SQL操作命令起作用)
spring事務回滾規則
指示spring事務管理器回滾一個事務的推薦方法是在當前事務的上下文內拋出異常
spring事務管理器會捕捉任何未處理的異常,然后依據規則決定是否回滾拋出異常的事務
默認配置下,spring只有在拋出的異常為運行時unchecked異常時才回滾該事務,也就是拋出的異常為RuntimeException的子類(Errors也會導致事務回滾),而拋出checked異常則不會導致事務回滾。
用 spring 事務管理器,由spring來負責數據庫的打開,提交,回滾.默認遇到運行期例外(throw new RuntimeException(“注釋”);)會回滾,即遇到不受檢查(unchecked)的例外時回滾;而遇到需要捕獲的例外(throw new Exception(“注釋”);)不會回滾,即遇到受檢查的例外(就是非運行時拋出的異常,編譯器會檢查到的異常叫受檢查例外或說受檢查異常)時,需我們指定方式來讓事務回滾要想所有異常都回滾,要加上 @Transactional( rollbackFor={Exception.class,其它異常}) .如果讓unchecked例外不回滾: @Transactional(notRollbackFor=RunTimeException.class)
注意事項:
@Transactional 使用位置 類上方、方法上方
Spring 建議不要在接口或者接口方法上使用該注解,因為這只有在使用基於接口的代理時它才會生效
當作用於類上時,該類的所有 public 方法將都具有該類型的事務屬性,同時,我們也可以在方法級別使用該標注來覆蓋類級別的定義。
方法的訪問權限為 public
@Transactional 注解應該只被應用到 public 方法上,這是由 Spring AOP 的本質決定的。在 protected、private 或者默認可見性的方法上使用 @Transactional 注解,這將被忽略,也不會拋出任何異常
默認情況下,只有來自外部的方法調用才會被AOP代理捕獲,也就是,類內部方法調用本類內部的其他方法並不會引起事務行為,即使被調用方法使用@Transactional注解進行修飾
例如一:同一個類中方法,A方法未使用此標簽,B使用了,C未使用,A 調用 B , B 調用 C ;則外部調用A之后,B的事務是不會起作用的
例如二:若是有上層(按照 Controller層、Service層、DAO層的順序)由Action 調用 Service 直接調用,發生異常會發生回滾;若間接調用,Action 調用 Service 中 的A 方法,A無@Transactional 注解,B有,A調用B,B的注解無效
其他
事務方法的嵌套調用會產生事務傳播
spring 的事務管理是線程安全的
父類的聲明的@Transactional會對子類的所有方法進行事務增強;子類覆蓋重寫父類方式可覆蓋其@Transactional中的聲明配置
類名上方使用@Transactional,類中方法可通過屬性配置覆蓋類上的@Transactional配置;比如:類上配置全局是可讀寫,可在某個方法上改為只讀