精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Spring事務失效常見的五種方式及其解決方案

開發 架構
本文總結了Spring 聲明式事務的源碼實現、五種常見的事務失效情況,并提供了相應的解決方案。

一、前言

在Web 開發中,Spring 框架已經成為了眾多開發者的首選。Spring 的聲明式事務管理是其中最重要的特性之一,它可以幫助我們簡化業務邏輯的復雜度,并且確保在出現異常情況時數據的一致性。

事務失效情況很常見,但我們只要注意,就可以避免事情發生!在本文中,我將詳細地介紹 Spring 聲明式事務的源碼實現和事務失效常見的五種情況,并給出有效的解決方案。

其實我們常說的事務失效是聲明式事務(@Transactional)的失效,本文也是從聲明式事務來進行演示的!

通過本文的學習,你將掌握如何正確地使用 Spring 的事務管理,減少生產事故。

「一定要保持數據一致性」。

二、@Transactional注解參數解讀

我們拿出幾個經常使用的參數來簡單介紹一下:

  • propagation:指定事務的傳播行為。其取值包括 REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER 和 NESTED 等。默認為 REQUIRED。 其中,REQUIRED 表示如果當前已經存在一個事務,則加入該事務,否則新建一個事務;而 REQUIRES_NEW 表示新建一個獨立的事務,如果當前已經存在事務,則掛起當前事務。后面就不一一說了,大家可以自行百度哈!
  • isolation:指定事務的隔離級別。其取值包括 DEFAULT、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ 和 SERIALIZABLE 等。默認為 DEFAULT。 其中,DEFAULT 表示采用數據庫的默認隔離級別.
  • timeout:指定事務的超時時間,單位為秒。默認為 -1,表示不設置超時時間。如果在規定時間內事務還未完成,則拋出 TransactionTimedOutException 異常。
  • readOnly:指定事務是否只讀,即是否允許修改數據。默認為 false,表示可以進行數據修改操作。如果將其設置為 true,則表示該事務僅能進行數據查詢操作,不能進行數據修改操作,這樣可以提高并發性能。
  • rollbackFor:指定哪些異常需要回滾事務。其取值為一個 Class 數組,其中每個元素表示一個異常類型。默認為空,表示只有拋出 RuntimeException 或 Error 類型的異常時才回滾事務。
  • noRollbackFor:指定哪些異常不需要回滾事務。其取值為一個 Class 數組,其中每個元素表示一個異常類型。默認為空,表示拋出任何異常都回滾事務。

三、聲明式事務源碼實現

聲明式事務實現類為:TransactionInterceptor ,下面我們來一起看看這個類!

源碼版本為Springboot2.7.1。

public class TransactionInterceptor extends TransactionAspectSupport 
 implements MethodInterceptor, Serializable{}

TransactionInterceptor UML圖:

圖片

聲明式事務主要是通過AOP實現,主要包括以下幾個節點:

  1. 啟動時掃描@Transactional注解:在啟動時,Spring Boot會掃描所有使用了@Transactional注解的方法,并將其封裝成TransactionAnnotationParser對象。
  2. AOP 來實現事務管理的核心類依然是 TransactionInterceptor。TransactionInterceptor 是一個攔截器,用于攔截使用了 @Transactional 注解的方法
  3. 將TransactionInterceptor織入到目標方法中:在AOP編程中,使用AspectJ編寫切面類,通過@Around注解將TransactionInterceptor織入到目標方法中。
  4. 在目標方法執行前創建事務:在目標方法執行前,TransactionInterceptor會調用PlatformTransactionManager創建一個新的事務,并將其納入到當前線程的事務上下文中。
  5. 執行目標方法:在目標方法執行時,如果發生異常,則將事務狀態標記為ROLLBACK_ONLY;否則,將事務狀態標記為COMMIT。
  6. 提交或回滾事務:在目標方法執行完成后,TransactionInterceptor會根據事務狀態(COMMIT或ROLLBACK_ONLY)來決定是否提交或回滾事務。

源碼:

@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
 // Work out the target class: may be {@code null}.
 // The TransactionAttributeSource should be passed the target class
 // as well as the method, which may be from an interface.
 Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

 // Adapt to TransactionAspectSupport's invokeWithinTransaction...
 return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
  @Override
  @Nullable
  public Object proceedWithInvocation() throws Throwable {
   return invocation.proceed();
  }
  @Override
  public Object getTarget() {
   return invocation.getThis();
  }
  @Override
  public Object[] getArguments() {
   return invocation.getArguments();
  }
 });
}

下面是核心處理方法,把不太重要的代碼忽略了,留下每一步的節點。

@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
 final InvocationCallback invocation) throws Throwable {
 // 獲取事務屬性
 final TransactionManager tm = determineTransactionManager(txAttr);
 // 準備事務
 TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
 // 執行目標方法
 Object retVal = invocation.proceedWithInvocation();
  // 回滾事務
 completeTransactionAfterThrowing(txInfo, ex);
 // 提交事務
 commitTransactionAfterReturning(txInfo);
}

四、五種失效和解決方案

圖片

下面我們從幾個情況來給大家展示失效場景并給出解決方案。

1、類沒有被 Spring 管理

public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addUser(User user) {
        userDao.addUser(user);
    }
}

如上代碼所示,UserServiceImpl 類沒有被聲明為 Spring Bean,因此其中的 addUser() 方法無法受到 Spring 事務管理的保護。 我們使用Spring,要把類交給Spring進行管理,不然是無法生效!

「解決方案:」 交給spring進行管理bean,在類上添加:@Service!

2、方法不是public修飾

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    @Transactional(rollbackFor = Exception.class)
    protected void addUser(User user) {
        userDao.addUser(user);
    }
}

我們上面說了聲明式事務是基于AOP實現的,AOP是通過代理模式實現的,即為目標對象生成一個代理對象,當調用代理對象的方法時,會自動添加事務的控制代碼。 在這種情況下,如果事務注釋所在的方法不是public的,則無法生成代理對象,因此事務代碼將無法添加到方法執行前后,導致事務失效。

其實這種情況還是不經常這么使用,我們基本都是使用接口和實現大部分都是public修飾的!

「解決方案:」 使用public來修飾方法。

3、異常被捕獲并處理了

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addUser(User user) {
        try {
            userDao.addUser(user);
        } catch (Exception e) {
            // 處理異常,但沒有拋出或重新拋出異常
            log.error("add user error", e);
        }
    }
}

如上代碼所示,如果 userDao.addUser() 方法拋出異常,但是在 UserServiceImpl.addUser() 中被捕獲并處理了,事務檢測不到有異常拋出,那么事務不會回滾。

「解決方案:」 catch 處理完成后,在重新把異常在拋出去:throw e。

4、同一個類中,方法內部調用

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public void addUser(User user) {
        doAddUser(user);
    }

    @Transactional(rollbackFor = Exception.class)
    public void doAddUser(User user) {
        userDao.addUser(user);
    }
}

Spring使用代理來實現事務控制,但是這種方法直接調用了this對象的方法,則無法通過代理來攔截該方法調用,從而使得事務失效。

「解決方案:」

推薦使用有兩種:

  • 使用ApplicationContext來獲取當前bean對象來調用doAddUser方法。
  • 在addUser方法加上@Transactional(rollbackFor = Exception.class)。

網上還有一些使用AopContext.currentProxy()拿到代理對象的、自己注入自己的、抽到單獨的bean里的 這里小編不是很推薦!

方法一完整展示:

如果覺得Service里注入ApplicationContext 不優雅,可以抽到單獨的工具bean里!

@Service
public class UserServiceImpl implements UserService {

 @Autowired
    private UserDao userDao;
    @Autowired
 private ApplicationContext applicationContext;

    @Override
    public void addUser(User user) {
     UserServiceImpl userService = applicationContext.getBean(UserServiceImpl.class);
        userService.doAddUser(user);
    }

    @Transactional(rollbackFor = Exception.class)
    public void doAddUser(User user) {
        userDao.addUser(user);
    }
}

5、MySQL存儲引警不支持事務

MyISAM 存儲引擎是 MySQL 的一種存儲引擎,它是 MySQL 5.1 版本之前的默認存儲引擎,它是不支持事務的。從 MySQL 5.5 版本開始,InnoDB 成為了 MySQL 的默認存儲引擎。我們想使用也可以切換到MyISAM引擎。

「解決方案:」 把mysql換到5.5以上使用InnoDB 存儲引擎。

「補充使用MyISAM 方式:」

  • 表從 InnoDB 引擎轉換為 MyISAM 引擎:使用 ALTER TABLE 命令來更改表的引擎類型。
ALTER TABLE table_name ENGINE = MyISAM;
  • 默認的存儲引擎設置為 MyISAM, 可以在 MySQL 配置文件中設置 default-storage-engine 參數。
default-storage-engine=MyISAM
  • 創建表時指定MyISAM 引擎 要將表的引擎類型設置為 MyISAM,請在 CREATE TABLE 語句中包含 ENGINE = MyISAM 子句
CREATE TABLE table_name (
    column1 datatype,
    column2 datatype,
    ...
) ENGINE = MyISAM;

五、總結

本文總結了Spring 聲明式事務的源碼實現、五種常見的事務失效情況,并提供了相應的解決方案。

當然還有很多情況:被final修飾、多線程調用、傳播行為使用不當、拋的異常不對應等等

理解 Spring 事務機制的,深入了解 Spring 事務的內部原理。同時,在使用聲明式事務的過程中,我們也可以針對自己的業務場景進行定制化的配置,比如指定特定的事務傳播機制、設置超時時間等,這些都有助于更好地應對復雜的業務場景和代碼需求。這樣才能真正地提高系統的可維護性、可擴展性和穩定性。

責任編輯:姜華 來源: 小王博客基地
相關推薦

2011-02-28 13:51:30

Spring事物配置

2009-06-19 18:26:38

Spring事務配置

2011-11-25 10:25:27

SpringJava

2020-03-31 16:13:26

分布式事務方案TCC

2022-12-19 08:23:34

2022-03-30 07:52:16

.NET應用程序C#

2018-10-10 10:23:53

數據庫RedisNoSQL

2023-04-14 14:54:29

2018-05-04 07:36:35

醫療行業物聯網IoT

2022-12-06 10:39:43

Spring事務失效

2020-08-20 20:51:17

打散算法打散法原算法

2024-03-26 12:08:53

分布式事務存儲

2021-06-28 09:00:00

Kubernetes容器云計算

2019-06-14 05:00:05

2022-02-23 12:07:20

分布式Spark數據傾斜

2024-09-09 08:29:25

2010-09-09 10:29:47

2023-05-06 15:32:04

2025-04-29 04:00:00

分布式事務事務消息

2020-06-08 22:33:42

物聯網IOT物聯網實施
點贊
收藏

51CTO技術棧公眾號

久久久com| 午夜精品久久久99热福利| 亚洲成人天堂网| 成人免费视屏| 91片在线免费观看| 国产欧美亚洲视频| 久久在线视频精品| 精品国产不卡| 欧美草草影院在线视频| 黄在线观看网站| 免费黄色在线| 97se亚洲国产综合自在线观| 国产精品美女www爽爽爽视频| 污软件在线观看| 五月综合久久| 日韩一区二区高清| 宅男噜噜噜66国产免费观看| 性国产高清在线观看| 久久亚洲精精品中文字幕早川悠里| 成人激情视频网| 特级西西444www大精品视频免费看| sdde在线播放一区二区| 亚洲福利精品在线| 精品亚洲视频在线| 一区二区三区短视频| 一区二区三区在线免费| 亚洲国产一区二区在线| 天天舔天天干天天操| 黑人精品欧美一区二区蜜桃| 日韩免费中文字幕| 国产成人亚洲精品自产在线| 欧美电影免费| 在线观看国产精品淫| 中国老熟女重囗味hdxx| 久久精品黄色| 色吊一区二区三区| 欧美激情 国产精品| 日本片在线看| 一区二区三区四区激情| 在线成人av电影| aaa在线观看| 欧美激情中文字幕一区二区| 久久精品女人的天堂av| 欧美熟妇交换久久久久久分类| 韩国精品久久久| 国产精品www色诱视频| 久久久久久91亚洲精品中文字幕| 狠色狠色综合久久| 欧美精品免费在线观看| 91视频综合网| 国产精品久久久久蜜臀| 日韩在线国产精品| 91ts人妖另类精品系列| 日韩一区电影| 中文字幕一区二区精品| 国产不卡在线观看视频| 日韩美女一区二区三区在线观看| 在线观看久久av| 久久日免费视频| 日韩精品一卡| 欧美成人免费全部| 婷婷色中文字幕| 激情成人亚洲| 97国产精品视频| 欧美成人高清电影在线| 欧美一区二区免费视频| 夜夜添无码一区二区三区| 1stkiss在线漫画| 亚洲综合色视频| 97视频久久久| 美女100%一区| 欧美日韩在线播放三区| 国产欧美一区二| 中文字幕日韩在线| 日韩av一区二区在线| av男人的天堂av| 久久免费精品视频在这里| 久久成人人人人精品欧| 国产在线视频第一页| 夜夜爽av福利精品导航| 国产成人精品网站| 97人妻精品一区二区三区视频 | 日本精品视频| 日韩成人中文字幕在线观看| 无码 人妻 在线 视频| 911久久香蕉国产线看观看| 欧美激情乱人伦一区| 日韩av大片在线观看| 热久久久久久久| 97人人做人人人难人人做| 日韩一级中文字幕| 国产精品色婷婷| 无码人妻精品一区二区蜜桃百度| 色是在线视频| 91精品国产91久久久久久最新毛片| 成人做爰69片免费| av在线不卡免费观看| 欧美精品激情视频| 中文字幕永久在线视频| 成人sese在线| 最新av在线免费观看| 一区一区三区| 精品久久久久久综合日本欧美| 无码国产69精品久久久久同性| 在线成人超碰| 国产精品久久999| 色婷婷激情五月| 18欧美亚洲精品| 人人干人人视频| 欧美亚洲色图校园春色| 美女少妇精品视频| 免费在线不卡av| wwwwxxxxx欧美| 日韩欧美一级在线| 国产精品.xx视频.xxtv| 精品国产麻豆免费人成网站| 尤物在线免费视频| 日本不卡视频在线观看| 精品人伦一区二区三区| 污污的网站在线看| 欧美日韩免费观看一区三区| 波多野结衣办公室33分钟| 韩国精品一区二区三区| 国产精彩精品视频| 亚洲欧美综合在线观看| 亚洲一区成人在线| 少妇欧美激情一区二区三区| 999视频精品| 国产精品视频网站| 国产51人人成人人人人爽色哟哟 | 亚洲天堂国产精品| 久久久蜜桃精品| 777久久久精品一区二区三区| 精品久久国产一区| 久久视频免费观看| 97在线公开视频| 国产精品久久久久永久免费观看 | 久久国产亚洲精品无码| 91精品短视频| 欧美日韩电影在线观看| 国产女人高潮毛片| 亚洲欧美另类小说| 中文字幕亚洲影院| 亚洲成人国产| 91性高湖久久久久久久久_久久99| av在线电影播放| 欧美日韩国产小视频| 亚洲激情图片网| 久久精品噜噜噜成人av农村| 亚洲综合视频一区| 亚洲日本中文| 欧美美女18p| 亚洲国产精品suv| 性做久久久久久免费观看| 亚洲婷婷在线观看| 国产精品久久777777毛茸茸 | 色鬼7777久久| 色婷婷精品大视频在线蜜桃视频| 性猛交ⅹxxx富婆video | 亚洲欧洲国产视频| 亚洲五月婷婷| 久久偷窥视频| 欧美日韩视频免费观看| 色偷偷偷亚洲综合网另类| 99久久精品国产一区二区成人| 洋洋av久久久久久久一区| 韩国三级hd两男一女| 性色av一区二区怡红| 日韩国产高清一区| 亚洲综合资源| 亚洲18私人小影院| 成a人片在线观看www视频| 欧美精品1区2区3区| 中文字幕在线2021| 99re热视频精品| 欧美一级裸体视频| 欧美+日本+国产+在线a∨观看| 国产精品xxx在线观看www| 欧美成人免费电影| 不卡av在线播放| 天堂网在线中文| 欧美性生交片4| 久操免费在线视频| 国产欧美日韩在线看| 毛片毛片毛片毛片毛| 99日韩精品| 永久域名在线精品| 欧美在线导航| 92福利视频午夜1000合集在线观看 | 伊人久久大香线蕉av超碰| 国产91|九色| 快射av在线播放一区| 亚洲二区在线播放视频| 91福利在线观看视频| 亚洲国产sm捆绑调教视频| 我不卡一区二区| 成人妖精视频yjsp地址| 一级特黄性色生活片| 黄色亚洲在线| 中文字幕av导航| 四虎影视精品| 99www免费人成精品| 国产精品久久久久久久久久齐齐| 欧美高清在线播放| 色欧美激情视频在线| 亚洲精品国产品国语在线| 91精东传媒理伦片在线观看| 欧美日韩国产在线看| 清纯粉嫩极品夜夜嗨av| 亚洲国产精品高清| 网站免费在线观看| 国产成人在线免费观看| 一道本视频在线观看| 99在线|亚洲一区二区| 大片在线观看网站免费收看| 国产欧美一区| 鲁鲁狠狠狠7777一区二区| 这里视频有精品| 91成人免费视频| 婷婷激情成人| 国产成人精品视频在线| 国产在线美女| 国内偷自视频区视频综合| 成人在线免费看黄| 久久精品91久久香蕉加勒比| 成人77777| 亚洲视频在线观看视频| 午夜av免费观看| 亚洲第一视频网| 亚洲AV无码乱码国产精品牛牛| 欧美日韩一区视频| а中文在线天堂| 色婷婷久久99综合精品jk白丝 | 成人免费网站在线观看视频| 色视频www在线播放国产成人| 国产福利片在线| 亚洲丝袜一区在线| 大片免费播放在线视频| 亚洲视频在线看| 狠狠色伊人亚洲综合网站l| 亚洲桃花岛网站| 激情综合闲人网| 一区二区三区国产在线观看| 免费人成黄页在线观看忧物| 亚洲精品一区二区三区婷婷月| 免费黄色片在线观看| 亚洲天堂2020| 69久久久久| 久久久国产成人精品| 91在线中文| 欧美精品激情视频| 一个人www视频在线免费观看| 欧美一性一乱一交一视频| 波多野结衣亚洲| 国产精品扒开腿做爽爽爽男男| 日韩欧美精品电影| 国产精品一区av| 国产精品**亚洲精品| 91福利入口| 男人的天堂久久| 免费亚洲精品视频| 秋霞欧美视频| 欧洲美女和动交zoz0z| 一区二区视频欧美| 国产主播在线看| 另类调教123区| 久久精品无码一区二区三区毛片| 成人性生交大片免费看视频在线| 国产真实乱人偷精品| 久久女同精品一区二区| ass极品国模人体欣赏| 亚洲男同1069视频| 人人干人人干人人干| 色欧美日韩亚洲| 97人人爽人人爽人人爽| 亚洲第一精品自拍| 国产区视频在线播放| 久久伊人色综合| 色网在线免费观看| 国产日本欧美在线观看| 999久久久久久久久6666| 欧美高清性xxxxhdvideosex| 99视频精品全国免费| 2019日韩中文字幕mv| 日本vs亚洲vs韩国一区三区 | 国产精品私人自拍| 久草视频免费在线播放| 日韩欧美成人免费视频| 91久久久久久久久久久久| 亚洲电影免费观看| 日本在线观看| 91禁外国网站| 国产精品麻豆| 日本成人三级电影网站| 欧美天堂亚洲电影院在线观看| 久久精品99国产| 国产高清在线观看免费不卡| 日韩av在线看免费观看| 亚洲美女一区二区三区| 久草视频在线观| 在线成人小视频| 九色在线免费| 久久久久国产精品一区| 福利视频一区| 国产一区二区在线网站| 色88久久久久高潮综合影院| 黄色一级在线视频| 国产精品夜夜嗨| 欧美一区二区三区观看| 色综合天天综合色综合av| 亚洲奶汁xxxx哺乳期| 久久精品亚洲一区| 成人免费福利| 久久riav二区三区| 亚洲夜间福利| 日本wwwxx| 最新热久久免费视频| 亚洲精品国产欧美在线观看| 日韩国产在线看| 女人黄色免费在线观看| 91系列在线播放| 天天射综合网视频| 免费看污污网站| 久久久高清一区二区三区| 久久久午夜影院| 精品国产乱码久久久久久浪潮 | 国产精品亚洲综合天堂夜夜| 蜜桃国内精品久久久久软件9| 日日摸日日碰夜夜爽无码| 国产成a人亚洲精品| 色在线观看视频| 欧美一区二区国产| 国产精品剧情一区二区在线观看| 国产精品三级久久久久久电影| 欧美日韩播放| 久久婷婷国产91天堂综合精品| 久久久久久久久久久黄色| 免费观看成人毛片| 日韩精品在线免费观看视频| 久草在线资源站手机版| 久久精品国产美女| 日日摸夜夜添夜夜添国产精品| 久久精品一区二区免费播放| 欧美日韩亚洲91| 国产最新视频在线| 国产精品老女人视频| 不卡av一区二区| 欧美成人乱码一二三四区免费| 国产精品看片你懂得| 91九色蝌蚪91por成人| 久久中文字幕国产| 中文字幕亚洲在线观看| 国自产拍偷拍精品啪啪一区二区| 久久亚洲一级片| 国产精品欧美综合| 久久精品中文字幕| aiai久久| jizzjizzxxxx| 国产日韩av一区二区| 一级爱爱免费视频| 欧美区二区三区| 精品女人视频| 玩弄japan白嫩少妇hd| 国产精品成人免费| 亚洲黄色在线播放| 欧美中文字幕视频在线观看| 精品久久视频| 黄色片免费网址| 午夜亚洲国产au精品一区二区| 裸体xxxx视频在线| 91久久中文字幕| 亚洲二区在线| 秋霞网一区二区三区| 日韩欧美国产综合| 亚洲黄色免费看| 色呦呦网站入口| 99久久99久久综合| 亚洲在线观看av| 久久久久亚洲精品成人网小说| 亚洲人成网77777色在线播放| 亚洲精品www.| 午夜精品福利久久久| 无遮挡的视频在线观看| 国产高清精品一区二区三区| 老司机精品福利视频| 国产三级国产精品国产国在线观看| 亚洲福利影片在线| 色诱色偷偷久久综合| 妞干网在线观看视频| 国产精品三级电影| 亚洲高清视频网站| 国产激情视频一区| 精品动漫av| 欧美a级片免费看| 亚洲精品综合久久中文字幕| 粉嫩av国产一区二区三区| 777久久久精品一区二区三区| 亚洲男人的天堂在线观看| 好男人免费精品视频| 国产精品初高中精品久久 |