<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          透徹的掌握 Spring 中 @transactional 的使用

          共 4931字,需瀏覽 10分鐘

           ·

          2021-09-01 11:38

          你知道的越多,不知道的就越多,業(yè)余的像一棵小草!

          你來,我們一起精進!你不來,我和你的競爭對手一起精進!

          編輯:業(yè)余草

          推薦:https://www.xttblog.com/?p=5263

          透徹的掌握 Spring 中 @transactional 的使用

          事務管理是應用系統(tǒng)開發(fā)中必不可少的一部分。Spring 為事務管理提供了豐富的功能支持。

          聲明式事務有兩種方式,一種是在配置文件(xml)中做相關的事務規(guī)則聲明,另一種是基于 @Transactional 注解的方式。注釋配置是目前流行的使用方式。

          一、@Transactional 注解管理事務的實現步驟

          使用 @Transactional 注解管理事務的實現步驟分為兩步。

          第一步,在 xml 配置文件中添加事務配置信息。

          <tx:annotation-driven />

          <bean id="transactionManager" 
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

              <property name="dataSource" ref="dataSource" />
          </bean>

          第二步,將 @Transactional 注解添加到合適的方法上,并設置合適的屬性信息。

          @Transactional 注解的屬性信息

          屬性名說明
          name當在配置文件中有多個 TransactionManager , 可以用該屬性指定選擇哪個事務管理器。
          propagation事務的傳播行為,默認值為 REQUIRED。
          isolation事務的隔離度,默認值采用 DEFAULT。
          timeout事務的超時時間,默認值為-1。如果超過該時間限制但事務還沒有完成,則自動回滾事務。
          read-only指定事務是否為只讀事務,默認值為 false;為了忽略那些不需要事務的方法,比如讀取數據,可以設置 read-only 為 true。
          rollback-for用于指定能夠觸發(fā)事務回滾的異常類型,如果有多個異常類型需要指定,各類型之間可以通過逗號分隔。
          no-rollback-for拋出 no-rollback-for 指定的異常類型,不回滾事務。

          除此以外,@Transactional 注解也可以添加到類級別上。當把 @Transactional 注解放在類級別時,表示所有該類的公共方法都配置相同的事務屬性信息。

          方法級別的事務屬性信息會覆蓋類級別的相關配置信息。

          @Transactional 注解的標注于類上:

          @Transactional(propagation= Propagation.SUPPORTS,readOnly=true)
          @Service(value ="employeeService")
          public class EmployeeService

          二、注解方式的事務使用注意事項

          當您對 Spring 的基于注解方式的實現步驟和事務內在實現機制有較好的理解之后,就會更好的使用注解方式的事務管理,避免當系統(tǒng)拋出異常,數據不能回滾的問題。

          1. 正確的設置@Transactional 的 propagation 屬性

          本來期望目標方法進行事務管理,但若是錯誤的配置這三種 propagation,事務將不會發(fā)生回滾。

          1. TransactionDefinition.PROPAGATION_SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續(xù)運行。
          2. TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務方式運行,如果當前存在事務,則把當前事務掛起。
          3. TransactionDefinition.PROPAGATION_NEVER:以非事務方式運行,如果當前存在事務,則拋出異常。

          2. 正確的設置 @Transactional 的 rollbackFor 屬性

          默認情況下,如果在事務中拋出了未檢查異常(繼承自 RuntimeException 的異常)或者 Error,則 Spring 將回滾事務;除此之外的異常,Spring 都不會回滾事務!

          如果在事務中拋出其他類型的異常,并期望 Spring 能夠回滾事務,可以指定 rollbackFor。例:

          @Transactional(propagation= Propagation.REQUIRED, rollbackFor= MyException.class)

          若在目標方法中拋出的異常是 rollbackFor 指定的異常的子類,事務同樣會回滾。

          3. @Transactional 只能應用到 public 方法才有效

          只有 @Transactional 注解應用到 public 方法,才能進行事務管理。

          Spring AOP 會檢查目標方法的修飾符是不是 public,若不是 public,就不會獲取 @Transactional 的屬性配置信息,最終會造成不會用 TransactionInterceptor 來攔截該目標方法進行事務管理。

          4. 避免 Spring 的 AOP 的自調用問題

          在 Spring 的 AOP 代理下,只有目標方法由外部調用,目標方法才由 Spring 生成的代理對象來管理,這會造成自調用問題。

          若同一類中的其他沒有 @Transactional 注解的方法內部調用有 @Transactional 注解的方法,有 @Transactional 注解的方法的事務被忽略,不會發(fā)生回滾。

          @Service
          public class OrderService {
              private void insert() {
                  insertOrder();
              }

              @Transactional
              public void insertOrder() {
                  //insert log info
                  //insertOrder
                  //updateAccount
              }
          }

          insertOrder 盡管有@Transactional 注解,但它被內部方法 insert 調用,事務被忽略,出現異常事務不會發(fā)生回滾。

          2. 三大問題

          數據庫事務的正確執(zhí)行的 4 個基本要素是 原子性(「A」tommicity)、一致性(「C」onsistency)、隔離性(「I」solation) 和 持久性(「D」urability)。

          原子性 : 整個事務中的操作,要么全部完成,要么全部不完成,不可能停滯在中間某個環(huán)節(jié),僅完成一部分。

          一致性 : 指一個事務可以改變數據庫狀態(tài)。食物必須始終保持系統(tǒng)處于一致狀態(tài),不管任何給定時間有多少并發(fā)事務。

          隔離性 : 之兩個事務之間的隔離級別。

          持久性 : 在事務完成以后,該事務對數據庫所做的更改便持久保存在數據庫中,并不會被回滾。

          三大問題從 嚴重 到 輕度 以此如下:

          「臟讀問題」

          時刻事務一(老公)事務二(老婆)
          T1查詢余額,顯示10k——
          T2——查詢余額,顯示 10k
          T3——網購 1千,顯示 9k
          T4請客吃飯開銷 1k,顯示余額 8k——
          T5提交事務——
          T6——回滾事務
          T7——最終余額 8k

          所謂臟讀,指的就是讀到了“臟”數據,即一個事務讀取到了另一個事務未提交的數據。

          「不可重復讀問題」

          時刻事務一(老公)事務二(老婆)
          T1查詢余額,顯示10k——
          T2——查詢余額,顯示 10k
          T3——網購,開銷 1k,余額 9k
          T4請客吃飯,預計開銷 2k——
          T5——網購,開銷 8k,余額 1k
          T6——提交事務
          T7吃完買單,顯示余額1k,不夠付賬。——

          不可重復讀,指的是理論上的同一條數據,重復讀取,居然會不一樣,不具備可重復性。

          「幻讀問題」

          時刻事務一(老公)事務二(老婆)
          T1——查詢信用卡消費記錄,顯示 10 條記錄
          T2網購——
          T3提交事務——
          T4——打印消費記錄,有11條記錄

          幻讀,和不可重復讀類似,第二次讀取的數據相較于第一次居然發(fā)生了變化,仿佛看到了幻覺。

          不可重復讀 和 幻讀 有一定的相似性,都是指(在本人未改變的情況下)第二次讀取的數據,與第一次讀取結果不一樣。不過它們描述的側重點(及造成的影響程度)不一樣。

          • 不可重復讀問題,強調的是某一條數據的內容在“我”兩次讀取間,發(fā)生了改變。(因為 update 語句)
          • 幻讀問題,強調的整個數據的數據總量,在“我”兩次讀取間,發(fā)生了改變。(因為 insert / delete 語句)
          • 幻讀問題 造成的危害要小于 不可重復讀問題。

          3. 四個隔離級別

          隔離級別表示:「當“我”操作這張表時,“其他人”對這張表還有多大的操作權限」 ?!拔摇钡母綦x級別越高,其他人的權利就越小,那么“他”要執(zhí)行他想要執(zhí)行的操作而沒有權限時,那就只能 「等」“我”操作完 。

          數據庫領域有四個隔離級別(注意,這并非 Java 中特有的概念),針對于上述三大問題,四個隔離級別,從 解決不了任何問題解決所有問題,每一級多解決一個問題。

          隔離級別解決問題備注
          READ_UNCOMMITTED解決不了任何問題——
          READ_COMMITTED可以解決臟讀問題——
          REPEATABLE_READ可以解決不可重復讀問題包括解決臟讀問題
          SERIALIZABLE解決幻讀問題包括解決不可重復讀臟讀問題

          4. 傳播機制

          傳播行為含義備注
          REQUIRED當方法調用時,如果不存在當前事務,那么就創(chuàng)建事務;如果之前已經存在了事物,那么就沿用之前的事務。默認值
          SUPPORTS當方法調用時,如果不存在當前事務,就不啟用事務;如果當前啟用事務,那么就沿用當前事務。——
          MANATORY方法必須在事務內運行。如果不存在當前事務,則直接拋出異常。
          REQUIRES_NEW無論是否存在當前事務,方法都會在新的事務中運行總是開啟一個新事務,執(zhí)行本方法。
          NOT_SUPPORTED不支持事務,不存在當前事務也不會創(chuàng)建新事務;如果存在當前事務則掛起它,直到方法結束后才恢復當前事務適用于那些不支持事務的數據庫和SQL語句
          NEVER不支持事務。MANATORY 的“反面”,如果存在當前事務,就直接拋出異常。
          NESTED嵌套事務。REQUIRES_NEW 的高級版支持當前事務中使用保存點(savepoint),可以回滾到保存點;如果當前事務沒有保存點,則完全等價于 REQUIRES_NEW

          毫無疑問,最常用的是 REQUIRED,其次是 REQUIRES_NEW 。它們是最常見的業(yè)務處理方式,其它方式都是用于處理特定的業(yè)務。

          傳播機制本質上描述的是:在一個整體行為中,一個部分行為的失敗,會不會對整體行為造成影響,以及造成何種影響。

          瀏覽 50
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  操B视频在线 | 乱日韩视频 | 91香蕉视频1区 | 在线日韩在线 | 十八禁在线网址 |