Spring事務的本質其實就是數據庫對事務的支持,沒有數據庫的事務支持,spring是無法提供事務功能的。對於純JDBC操作數據庫,想要用到事務,可以按照以下步驟進行:
使用Spring的事務管理功能後,我們可以不再寫步驟 2 和 4 的代碼,而是由Spirng 自動完成。 那麼Spring是如何在我們書寫的 CRUD 之前和之後開啟事務和關閉事務的呢?解決這個問題,也就可以從整體上理解Spring的事務管理實現原理了。下面簡單地介紹下,注解方式為例子
所謂spring事務的傳播屬性,就是定義在存在多個事務同時存在的時候,spring應該如何處理這些事務的行為。這些屬性在TransactionDefinition中定義,具體常量的解釋見下表:
常量名稱 常量解釋 PROPAGATION_REQUIRED 支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇,也是 Spring 默認的事務的傳播。 PROPAGATION_REQUIRES_NEW 新建事務,如果當前存在事務,把當前事務掛起。新建的事務將和被掛起的事務沒有任何關系,是兩個獨立的事務,外層事務失敗回滾之後,不能回滾內層事務執行的結果,內層事務失敗拋出異常,外層事務捕獲,也可以不處理回滾操作 PROPAGATION_SUPPORTS 支持當前事務,如果當前沒有事務,就以非事務方式執行。 PROPAGATION_MANDATORY 支持當前事務,如果當前沒有事務,就拋出異常。 PROPAGATION_NOT_SUPPORTED 以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。 PROPAGATION_NEVER 以非事務方式執行,如果當前存在事務,則拋出異常。 PROPAGATION_NESTED如果一個活動的事務存在,則運行在一個嵌套的事務中。如果沒有活動事務,則按REQUIRED屬性執行。它使用了一個單獨的事務,這個事務擁有多個可以回滾的保存點。內部事務的回滾不會對外部事務造成影響。它只對DataSourceTransactionManager事務管理器起效。
髒讀:一事務對數據進行了增刪改,但未提交,另一事務可以讀取到未提交的數據。如果第一個事務這時候回滾了,那麼第二個事務就讀到了髒數據。
不可重復讀:一個事務中發生了兩次讀操作,第一次讀操作和第二次操作之間,另外一個事務對數據進行了修改,這時候兩次讀取的數據是不一致的。
幻讀:第一個事務對一定范圍的數據進行批量修改,第二個事務在這個范圍增加一條數據,這時候第一個事務就會丟失對新增數據的修改。
總結:
隔離級別越高,越能保證數據的完整性和一致性,但是對並發性能的影響也越大。
大多數的數據庫默認隔離級別為 Read Commited,比如 SqlServer、Oracle
少數數據庫默認隔離級別為:Repeatable Read 比如: MySQL InnoDB