亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot中的事務全方位詳解

 更新時間:2023年08月14日 10:52:09   作者:Pluto372  
這篇文章主要介紹了SpringBoot中的事務全方位詳解,在Spring中,事務有兩種實現方式,分別是編程式事務管理和聲明式事務管理兩種方式,文中舉例詳細說明了這兩種事務,需要的朋友可以參考下

SpringBoot事務的基本介紹

事務管理方式

在Spring中,事務有兩種實現方式,分別是編程式事務管理和聲明式事務管理兩種方式。

  • 編程式事務管理: 編程式事務管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager。對于編程式事務管理,spring推薦使用TransactionTemplate。
  • 聲明式事務管理: 建立在AOP之上的。其本質是對方法前后進行攔截,然后在目標方法開始之前創(chuàng)建或者加入一個事務,在執(zhí)行完目標方法之后根據執(zhí)行情況提交或者回滾事務。 聲明式事務管理不需要入侵代碼,通過@Transactional就可以進行事務操作,更快捷而且簡單,推薦使用。

編程式事務管理:

1、使用 TransactionTemplate 來管理事務:

@Autowired
private TransactionTemplate transactionTemplate;
public void testTransaction() {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                try {
                    // ....  業(yè)務代碼
                } catch (Exception e){
                    //回滾
                    transactionStatus.setRollbackOnly();
                }
            }
        });
}

2、使用 TransactionManager 來管理事務:

@Autowired
private PlatformTransactionManager transactionManager;
public void testTransaction() {
  TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
          try {
               // ....  業(yè)務代碼
              transactionManager.commit(status);
          } catch (Exception e) {
              transactionManager.rollback(status);
          }
}

聲明式事務管理:

  @Transactional
    public void testTransactional(){
    }

事務提交方式

默認情況下,數據庫處于自動提交模式。

每一條語句處于一個單獨的事務中,在這條語句執(zhí)行完畢時,如果執(zhí)行成功則隱式的提交事務,如果執(zhí)行失敗則隱式的回滾事務。

對于正常的事務管理,是一組相關的操作處于一個事務之中,因此必須關閉數據庫的自動提交模式。

不過,這個我們不用擔心,spring會將底層連接的自動提交特性設置為false。

也就是在使用spring進行事物管理的時候,spring會將是否自動提交設置為false,等價于JDBC中的 connection.setAutoCommit(false);,在執(zhí)行完之后在進行提交,connection.commit(); 。

事務隔離級別

隔離級別是指若干個并發(fā)的事務之間的隔離程度。

TransactionDefinition 接口中定義了五個表示隔離級別的常量:

  • TransactionDefinition.ISOLATION_DEFAULT:這是默認值,表示使用底層數據庫的默認隔離級別。對大部分數據庫而言,通常這值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED:該隔離級別表示一個事務可以讀取另一個事務修改但還沒有提交的數據。該級別不能防止臟讀,不可重復讀和幻讀,因此很少使用該隔離級別。比如PostgreSQL實際上并沒有此級別。
  • TransactionDefinition.ISOLATION_READ_COMMITTED:該隔離級別表示一個事務只能讀取另一個事務已經提交的數據。該級別可以防止臟讀,這也是大多數情況下的推薦值。
  • TransactionDefinition.ISOLATION_REPEATABLE_READ:該隔離級別表示一個事務在整個過程中可以多次重復執(zhí)行某個查詢,并且每次返回的記錄都相同。該級別可以防止臟讀和不可重復讀。
  • TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事務依次逐個執(zhí)行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止臟讀、不可重復讀以及幻讀。但是這將嚴重影響程序的性能。通常情況下也不會用到該級別。

事務傳播行為

當事務方法被另外一個事務方法調用時,必須指定事務應該如何傳播,例如,方法可能繼續(xù)在當前事務中執(zhí)行,也可以開啟一個新的事務,在自己的事務中執(zhí)行。

  • TransactionDefinition.PROPAGATION_REQUIRED:默認的事務傳播行為,指的是如果當前存在事務,則加入該事務;如果當前沒有事務,則創(chuàng)建一個新的事務。更確切地意思是: 如果外部方法沒有開啟事務的話,Propagation.REQUIRED 修飾的內部方法會開啟自己的事務,且開啟的事務相互獨立,互不干擾。 如果外部方法開啟事務并且是 Propagation.REQUIRED 的話,所有 Propagation.REQUIRED 修飾的內部方法和外部方法均屬于同一事務 ,只要一個方法回滾,整個事務都需要回滾。

也就是說如果a方法和b方法都添加了注解,在默認傳播模式下,a方法內部調用b方法,會把兩個方法的事務合并為一個事務。

  • TransactionDefinition.PROPAGATION_REQUIRES_NEW:創(chuàng)建一個新的事務,如果當前存在事務,則把當前事務掛起。也就是說不管外部方法是否開啟事務,Propagation.REQUIRES_NEW 修飾的內部方法都會開啟自己的事務,且開啟的事務與外部的事務相互獨立,互不干擾。當類A中的 a 方法用默認 Propagation.REQUIRED模式,類B中的 b方法加上采用 Propagation.REQUIRES_NEW模式,然后在 a 方法中調用 b方法操作數據庫,然而 a方法拋出異常后,b方法并沒有進行回滾,因為Propagation.REQUIRES_NEW會暫停 a方法的事務 ,總結就是a不影響b,b影響a
  • TransactionDefinition.PROPAGATION_SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續(xù)運行。
  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務方式運行,如果當前存在事務,則把當前事務掛起。
  • TransactionDefinition.PROPAGATION_NEVER:以非事務方式運行,如果當前存在事務,則拋出異常。
  • TransactionDefinition.PROPAGATION_MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。
  • TransactionDefinition.PROPAGATION_NESTED:如果當前存在事務,則創(chuàng)建一個事務作為當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價于TransactionDefinition.PROPAGATION_REQUIRED。

事務回滾規(guī)則

指示spring事務管理器回滾一個事務的推薦方法是在當前事務的上下文內拋出異常。

spring事務管理器會捕捉任何未處理的異常,然后依據規(guī)則決定是否回滾拋出異常的事務。

默認配置下,spring只有在拋出的異常為運行時unchecked異常時才回滾該事務,也就是拋出的異常為RuntimeException的子類(Errors也會導致事務回滾),而拋出checked異常則不會導致事務回滾。

可以明確的配置在拋出那些異常時回滾事務,包括checked異常。

也可以明確定義那些異常拋出時不回滾事務。

事務常用配置

  • readOnly:該屬性用于設置當前事務是否為只讀事務,設置為true表示只讀,false則表示可讀寫,默認值為false。例如:@Transactional(readOnly=true);
  • rollbackFor: 該屬性用于設置需要進行回滾的異常類數組,當方法中拋出指定異常數組中的異常時,則進行事務回滾。例如:指定單一異常類:@Transactional(rollbackFor=RuntimeException.class)指定多個異常類:@Transactional(rollbackFor={RuntimeException.class, Exception.class});
  • rollbackForClassName: 該屬性用于設置需要進行回滾的異常類名稱數組,當方法中拋出指定異常名稱數組中的異常時,則進行事務回滾。例如:指定單一異常類名稱@Transactional(rollbackForClassName=”RuntimeException”)指定多個異常類名稱:@Transactional(rollbackForClassName={“RuntimeException”,”Exception”})。
  • noRollbackFor:該屬性用于設置不需要進行回滾的異常類數組,當方法中拋出指定異常數組中的異常時,不進行事務回滾。例如:指定單一異常類:@Transactional(noRollbackFor=RuntimeException.class)指定多個異常類:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})。
  • noRollbackForClassName:該屬性用于設置不需要進行回滾的異常類名稱數組,當方法中拋出指定異常名稱數組中的異常時,不進行事務回滾。例如:指定單一異常類名稱:@Transactional(noRollbackForClassName=”RuntimeException”)指定多個異常類名稱:@Transactional(noRollbackForClassName={“RuntimeException”,”Exception”})。
  • propagation : 該屬性用于設置事務的傳播行為。例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)。
  • isolation:該屬性用于設置底層數據庫的事務隔離級別,事務隔離級別用于處理多事務并發(fā)的情況,通常使用數據庫的默認隔離級別即可,基本不需要進行設置。
  • timeout:該屬性用于設置事務的超時秒數,默認值為-1表示永不超時。也就是指一個事務所允許執(zhí)行的最長時間,如果在超時時間內還沒有完成的話,就自動回滾。假如事務的執(zhí)行時間格外的長,由于事務涉及到對數據庫的鎖定,就會導致長時間運行的事務占用數據庫資源。

@Transaction失效場景

1、訪問權限問題 (只有public方法會生效)

java的訪問權限主要有四種:private、default、protected、public,它們的權限從左到右,依次變大。spring要求被代理方法必須得是public的。

我們自定義的事務方法如果它的訪問權限不是public,會導致事務失效。

 	@Transactional
    private void testTransactional() {
    }

2、方法用final修飾,不會生效

有時候,某個方法不想被子類重新,這時可以將該方法定義成final的。

普通方法這樣定義是沒問題的,但如果將事務方法定義成final,會導致事務失效

 	@Transactional
    public final void testTransactional() {
    }

3、同一個類中的方法直接內部調用,會導致事務失效

@Service
public class TransactionalTest implements TransactionalService{
    @Override
    public  void testTransactional() {
        transactional();
    }
    @Transactional
    public  void  transactional(){}
}

文章開頭說道,聲明式事務管理是建立在AOP之上的。AOP的實現原理是動態(tài)代理。

一個方法調用本類的其他方法是不會走代理,原因是在InvocationHandlerImpl#invoke中method.invoke(subject, args);

這里調用的是目標類subject的方法,直接執(zhí)行目標類方法,不會執(zhí)行代理類的方法。?

因為JDK動態(tài)代理采用的是接口實現的方式,通過反射調用目標類的方法,此時如果調用本類的方法,this指的是目標類,并不是代理類所以不會走代理。

不走代理,事務自然會失效。

編寫新的sevice

這個方法非常簡單,只需要新加一個Service方法,把@Transactional注解加到新Service方法上,把需要事務執(zhí)行的代碼移到新方法中。

自己注入自己

@Service
public class TransactionalTest implements TransactionalService{
    @Resource
   private TransactionalTest transactionalTest;
    @Override
    public  void testTransactional() {
        transactionalTest.transactional();
    }
    @Transactional
    public  void  transactional(){}
}

如果不想再新加一個Service類,在該Service類中注入自己。

完全不用擔心循環(huán)依賴的問題,spring ioc內部的三級緩存保證了它,不會出現循環(huán)依賴問題。

4、事務方法中使用try-catch捕獲處理

   @Transactional
    public  void  transactional(){
        try{
        ....
        }catch(Exception e){
            logger.error("",e);
        }
    }

事務@Transactional由spring控制時,它會在拋出異常的時候進行回滾。如果自己使用try-catch捕獲處理了,是不生效的。

如果想事務生效可以進行手動回滾或者在catch里面將異常拋出【throw new RuntimeException();】

事務手動回滾

  try{
      ...
  }catch(Exception e){
      log.error("fail",e);
      TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
      return false;
  }

回滾部分異常 使用【Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint(); 】設置回滾點。

使用【TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);】回滾到savePoint。

@Override
@Transactional(rollbackFor = Exception.class)
public Object submitOrder (){  
    success();  
    //只回滾以下異常,
    Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
    try {  
        exception(); 
     } catch (Exception e) {  
        e.printStackTrace();     
        // 手工回滾事務
        TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
        return response.error();
     }  
    return response.success();
}

到此這篇關于SpringBoot中的事務全方位詳解的文章就介紹到這了,更多相關SpringBoot中的事務內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java AtomicInteger類的重要方法和特性

    Java AtomicInteger類的重要方法和特性

    AtomicInteger是Java中的一個類,用于實現原子操作的整數,AtomicInteger類主要用于處理整數類型的原子操作,本文給大家介紹Java AtomicInteger類的重要方法和特性,感興趣的朋友一起看看吧
    2023-10-10
  • 解析Spring Data JPA的Audit功能之審計數據庫變更

    解析Spring Data JPA的Audit功能之審計數據庫變更

    Spring Data JPA 提供了Audit審計功能,用來記錄創(chuàng)建時間、創(chuàng)建人、修改時間、修改人等,下面來詳細講解下審計數據庫變更
    2021-06-06
  • Maven下載依賴的順序及配置文件小結

    Maven下載依賴的順序及配置文件小結

    本文主要介紹了Maven下載依賴的順序及配置文件小結,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-07-07
  • springboot中引入日志文件生成的配置詳解

    springboot中引入日志文件生成的配置詳解

    本文主要介紹了springboot中引入日志文件生成的配置詳解,包括日志級別的設置、日志格式的配置以及日志輸出的位置等,從而幫助開發(fā)者更好地進行開發(fā)與調試
    2023-10-10
  • SpringMVC框架post提交數據庫出現亂碼解決方案

    SpringMVC框架post提交數據庫出現亂碼解決方案

    這篇文章主要介紹了SpringMVC框架post提交數據庫出現亂碼解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • Java仿淘寶首頁分類列表功能的示例代碼

    Java仿淘寶首頁分類列表功能的示例代碼

    這篇文章主要介紹了仿淘寶分類管理功能的示例代碼,具有很好的參考價值,希望對大家有所幫助,也給大家做個參考
    2018-05-05
  • 一文詳解Java中Map和Set接口的使用方法

    一文詳解Java中Map和Set接口的使用方法

    Map和set是一種專門用來進行搜索的容器或者數據結構,其搜索的效率與其具體的實例化子類有關,可能在查找時進行一些插入和刪除的操作,即動態(tài)查找,那上述兩種方式就不太適合了,本節(jié)介紹的Map和Set是一種適合動態(tài)查找的集合容器,需要的朋友可以參考下
    2024-08-08
  • Java日常練習題,每天進步一點點(42)

    Java日常練習題,每天進步一點點(42)

    下面小編就為大家?guī)硪黄狫ava基礎的幾道練習題(分享)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-07-07
  • SpringBoot入門之集成JSP的示例代碼

    SpringBoot入門之集成JSP的示例代碼

    這篇文章主要介紹了SpringBoot入門之集成JSP的示例代碼,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • Mybatis使用foreach批量更新數據報無效字符錯誤問題

    Mybatis使用foreach批量更新數據報無效字符錯誤問題

    這篇文章主要介紹了Mybatis使用foreach批量更新數據報無效字符錯誤問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08

最新評論