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

盤點Spring事務失效的4種寫法及解決方案,Review代碼再也不慌了

開發 前端
事務是我們日常開發工作中無法避免的一個功能,深刻理解事務的運行機制,正確使用事務的聲明式操作,才能讓我們寫出更健壯的代碼。

1、非運行時異常導致事務無法回滾

我們知道,Spring是通過AOP的方式來實現事務的,而在處理事務的過程中,Spring只有捕獲到RuntimeException或者Error的時候才會觸發回滾操作,如果我們在代碼中拋出的是非運行時異常,而又沒有特殊配置的話,事務就會無法回滾。

下面我們以一個簡單的例子,復現一下這種情況,以及針對這種情況的解決方案。

本文Springboot版本:2.7.6,數據源為MySQL。

首先創建一個測試用的User對象:

@Data
public class User {
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
private String pwd;
}

建表語句:

CREATE TABLE user  (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`pwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB;

測試邏輯:往user表插入一條數據,如果插入成功,就拋出exception異常,測試數據是否回滾。

@Service
@AllArgsConstructor
public class DemoService {
private final UserMapper userMapper;

@Transactional
public ResponseEntity<Object> addUser(User user) throws Exception {
int insert = this.userMapper.insert(user);
if (insert > 0) {
throw new Exception("異常回滾測試");
}
return ResponseEntity.ok().build();
}
}

新建測試方法:

@Test
public void addUserTest() throws Exception {
User user = new User();
user.setName("測試");
user.setPwd("123456");
this.demoService.addUser(user);
}

運行測試方法,從控制臺可以看到,我們手動指定的異常被成功拋出。

但是,當異常發生時,事務并沒有被回滾,數據依然被插入到了數據庫。

解決辦法:
1,將異常包裝成運行時異常:throw new RuntimeException("異常回滾測試");

2,在@Transactional指定回滾的異常類型,@Transactional(rollbackFor = Exception.class)。

一般來說,使用第二種方式會更清晰一些,但是有些朋友往往會忘記手動指定回滾的異常類型,進而導致非預期的bug產生。

2、通過this調用本類事務方法導致的事務無法回滾

隨著業務的發展,核心業務代碼會越來越多,同一個方法也會越寫越長。我們為了使代碼邏輯更加高內聚低耦合,會將功能相同的代碼進行封裝成一個個的子方法。

但是,如果我們對事務的運行機制了解不透徹,隨意在同一個類中通過this調用事務方法,就可能導致非預期的bug。

@Service
@RequiredArgsConstructor
public class DemoService {
private final UserMapper userMapper;
public ResponseEntity<Object> addUser(User user){
//注意這一行
this.doAddUser(user);
return ResponseEntity.ok().build();
}

@Transactional(rollbackFor = Exception.class)
public void doAddUser(User user) {
int insert = this.userMapper.insert(user);
if (insert > 0) {
throw new RuntimeException("測試添加異常回滾");
}
}
}

如以上代碼所示,在addUser方法中調用了事務方法doAddUser,如果數據插入成功,就拋出一個異常,測試數據是否能夠回滾。

通過測試用例可以看到,異常已經拋出,但是數據庫中卻成功的插入了數據,我們期望的數據并沒有回滾。

原因探究:

原因其實很簡單,通過this方法調用時,Spring的代理沒能起作用,事務自然也就無法介入,關于這一點的原理在之前的文章中也有分析過,感興趣的朋友可以去看一看。

有的朋友可能會說,項目的代碼已經是這樣了,再將老方法重寫到新類中也不現實,有沒有辦法改動較小的方式呢?

其實很簡單,現在事務失效的原因是代理失效,那么想辦法讓代理重新生效就行了。

我們在本類中注入一個當前對象,這個對象可以被Spring代理,那么這個對象的方法自然也可以被代理。

@Service
@RequiredArgsConstructor
public class DemoService {
private final UserMapper userMapper;
@Resource
private DemoService self;
public ResponseEntity<Object> addUser(User user){
//通過self引用使代理生效
this.self.doAddUser(user);
return ResponseEntity.ok().build();
}

@Transactional(rollbackFor = Exception.class)
public void doAddUser(User user) {
int insert = this.userMapper.insert(user);
if (insert > 0) {
throw new RuntimeException("測試添加異常回滾");
}
}
}

3、被聲明的事務方法是private類型

這種錯誤在博主剛工作時遇到挺多次的,不過現在現代IDE已經越來越智能了,對于這種情況會直接給出錯誤提示,所以這里提出這種錯誤只是告訴大家,事務方法是不能聲明為private的。

至于為什么不能是private,那自然還是和代理有關了。

4、嵌套事務異常導致事務被提前關閉而報錯

當使用嵌套事務時,需要明確指定事務的傳播范圍。

@Service
@RequiredArgsConstructor
public class DemoService {
private final UserMapper userMapper;
@Resource
private DemoService self;

@Transactional(rollbackFor = Exception.class)
public ResponseEntity<Object> addUser(User user) {
int insert = this.userMapper.insert(user);
if (insert > 0) {
try {
this.self.update(user);
} catch (Exception e) {
System.out.println("即使更新異常也不要影響添加數據");
}
}
return ResponseEntity.ok().build();
}

@Transactional(rollbackFor = Exception.class)
public void update(User user) {
user.setPwd("666666");
int update = this.userMapper.updateById(user);
if (update > 0) {
throw new RuntimeException("測試更新數據回滾");
}
}
}

如以上代碼,我們添加完一條數據之后,嘗試將密碼更新為666666,并且希望即使更新異常,也不要影響添加操作。

然而運行測試用例,我們會得到這樣一條錯誤信息:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only。

什么意思呢?就是當Spring處理事務時,發現事務已經被回滾了。

這是因為我們并沒有指定事務的傳播行為,默認情況下,Spring的事務傳播是REQUIRED,即:如果本來有事務,則加入該事務,如果沒有事務,則創建新的事務。

我們添加數據時啟動了一個事務,更新數據時,Spring判斷當前已經存在事務,所以就不再新建事務,而是加入當前事務。

但是當更新操作失敗時,需要對事務進行回滾,更新是沒問題的,正常回滾。

但是插入操作就不行了,當要提交插入操作的事務時,由于事務已經被回滾了,無法再次操作,Spring只好報錯來提示我們了。

如何處理呢?在更新操作上指明事務的傳播范圍就行。

@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public void update(User user){
user.setPwd("666666");
int update = this.userMapper.updateById(user);
if (update > 0) {
throw new RuntimeException("測試更新數據回滾");
}
}

再測試一下,發現插入操作的事務可以正常提交了。

總結

事務是我們日常開發工作中無法避免的一個功能,深刻理解事務的運行機制,正確使用事務的聲明式操作,才能讓我們寫出更健壯的代碼。

責任編輯:姜華 來源: 今日頭條
相關推薦

2023-05-26 07:19:49

Spring聲明式事務

2023-09-14 15:44:46

分布式事務數據存儲

2022-12-06 10:39:43

Spring事務失效

2021-04-14 15:17:08

Transaction代碼語言

2024-03-26 12:08:53

分布式事務存儲

2024-06-13 08:04:23

2020-03-31 16:13:26

分布式事務方案TCC

2010-09-02 15:18:42

CSSASP.NET

2024-09-09 08:29:25

2020-12-18 10:13:19

晉升職級協議

2025-04-29 04:00:00

分布式事務事務消息

2019-07-25 15:32:35

分布式事務微服務系統架構

2025-02-28 09:47:36

2024-05-22 19:10:18

跨域Web開發

2010-01-05 10:57:30

2024-01-29 08:28:01

Spring事務失效

2021-07-06 13:32:34

零信任網絡安全網絡攻擊

2019-03-12 10:30:29

開源備份Borg Backup

2023-03-08 12:39:47

架構

2021-09-04 07:56:44

Spring事務失效
點贊
收藏

51CTO技術棧公眾號

久久精品国产免费| 欧美激情15p| 亚洲免费av网站| 国产伦精品一区二区三区四区免费| 精品日韩免费| 99免费精品在线| 国产mv久久久| 污软件在线观看| 91成人福利| 狠狠做深爱婷婷久久综合一区| 三级三级久久三级久久18| 国产成人精品av在线观| 亚洲欧美日韩在线观看a三区| 中文字幕不卡在线视频极品| 天堂va欧美va亚洲va老司机| ww久久综合久中文字幕| 亚洲成a人片综合在线| 日韩精品欧美专区| 亚洲精品一区二区三区新线路| 农村老熟妇乱子伦视频| 欧美与亚洲与日本直播| 老司机成人影院| 精品视频日韩| 亚洲国产精品电影在线观看| 婷婷六月天在线| 91超碰免费在线| 国产精品美女久久久久久久久久久 | 亚洲天堂久久久久久久| 蜜桃日韩视频| 成人午夜免费福利| 久久99深爱久久99精品| 国产高清在线不卡| 国产女同在线观看| 午夜视频一区| 伦伦影院午夜日韩欧美限制| 懂色av蜜桃av| 妖精视频一区二区三区免费观看| 欧美成人精品高清在线播放| 日本77777| 日韩欧美精品一区二区综合视频| 欧美日韩亚洲国产一区| 日韩a∨精品日韩在线观看| 伊人影院在线视频| 日韩美女精品在线| 色综合久久久久久久久五月| 国产精品国产高清国产| 成人国产亚洲欧美成人综合网| 91亚洲va在线va天堂va国 | 色综合999| 亚洲免费观看在线观看| 伊人久久大香线蕉午夜av| 国产69久久| 国产午夜精品一区二区| 欧美综合77777色婷婷| 男人的天堂在线| 91亚洲男人天堂| 国产一区在线免费观看| 俄罗斯嫩小性bbwbbw| 国产成人免费xxxxxxxx| av一区和二区| 亚洲国产精品久久久久久6q | 精品久久久久久久大神国产| 欧美精品久久久久久久自慰| 超碰91在线观看| 婷婷综合另类小说色区| 国产精品333| 成人一区福利| 欧美日韩免费视频| 日韩av片免费观看| 精品一区二区三区四区五区| 欧美第一区第二区| 在线黄色免费网站| 蜜臀av免费一区二区三区| 一本大道久久加勒比香蕉| 国产在线免费av| 中文av一区| 欧美交受高潮1| 国产成人无码精品久在线观看 | 国产精品视频黄色| 九七电影院97理论片久久tvb| 欧美喷潮久久久xxxxx| 一级黄色免费毛片| 全球av集中精品导航福利| 国产一区二区三区直播精品电影 | 欧美专区在线视频| 中文字幕乱伦视频| 国产精品一区二区在线观看不卡| 国产欧美日韩综合精品二区| 国产中文在线观看| 中文字幕一区在线| 97超碰人人澡| 精品176极品一区| 欧美变态口味重另类| 一级黄色片大全| 久久精品亚洲人成影院 | 日本熟妇色xxxxx日本免费看| 亚洲永久网站| 亚洲a区在线视频| 偷拍自拍在线视频| 中文字幕亚洲欧美在线不卡| 韩日视频在线观看| 免费日韩成人| 日韩电影中文字幕av| 国产又粗又长又硬| 国产欧美一区二区三区国产幕精品| 国产精品日韩精品| 天堂在线观看av| 中文字幕永久在线不卡| 99热成人精品热久久66| 亚洲码欧美码一区二区三区| 亚洲小视频在线| 国产亚洲精品成人| 久久精品国产在热久久| 国新精品乱码一区二区三区18| 成人在线视频成人| 亚瑟在线精品视频| 波多野结衣网页| 精品一区二区三区在线| 性视频1819p久久| 国产绿帽一区二区三区| 国产性色一区二区| 久久久久久久午夜| 97品白浆高清久久久久久| www.日韩av.com| www.欧美色| 91香蕉视频污| 日韩人妻无码精品久久久不卡| 91精品在线免费视频| 国产一区二区三区精品久久久| 日本一区二区三区四区五区| 精品亚洲国内自在自线福利| 日韩免费电影一区二区三区| 在线天堂资源| 亚洲精品二三区| 国产在线观看99| 国产福利一区二区三区视频| 亚洲一区高清| 91天天综合| 伊人久久久久久久久久| 蜜臀99久久精品久久久久小说| 97久久超碰国产精品| 少妇人妻大乳在线视频| 豆花视频一区二区| 欧美激情久久久久| 国产视频一二三四区| 亚洲蜜臀av乱码久久精品| 九一精品久久久| 亚洲成av人电影| 91精品中文在线| 黄在线免费看| 91精品国产综合久久小美女| 免费国产羞羞网站美图| 激情六月婷婷久久| 欧美一级黄色录像片| 免费一级欧美在线大片| 欧美精品情趣视频| 亚洲av无码专区在线| 亚洲夂夂婷婷色拍ww47| 国产精品亚洲一区二区无码| 亚洲无毛电影| 精品久久一区二区三区蜜桃| 麻豆免费版在线观看| 精品丝袜一区二区三区| 在线观看国产区| 国产精品久99| 99精品视频国产| 欧美激情在线| 国产欧美在线一区二区| 亚洲欧洲高清| 一区二区三区四区在线观看视频| 中文人妻熟女乱又乱精品| 中文字幕在线观看不卡| 69亚洲乱人伦| 久久av在线| 性欧美18一19内谢| 白嫩白嫩国产精品| 欧美壮男野外gaytube| 在线免费看黄| 日韩精品自拍偷拍| 免费看一级视频| 中文字幕一区二区三区在线播放| 韩国三级与黑人| 亚洲尤物在线| 手机福利在线视频| 激情小说亚洲图片| 国产精品主播视频| f2c人成在线观看免费视频| 亚洲欧洲xxxx| 国产精品一区二区人人爽| 亚洲国产成人精品视频| 色欲狠狠躁天天躁无码中文字幕 | 在线观看免费视频国产| 亚洲影音一区| 裸体裸乳免费看| 久久99国内| 成人欧美一区二区三区视频xxx| 日韩精品美女| 久久在线观看视频| 免费黄色在线视频网站| 日韩一区二区三区在线观看| 超碰在线观看91| 一区二区激情视频| 日本欧美一区二区三区不卡视频 | 国产亚洲无码精品| 久久99精品一区二区三区| 青娱乐自拍偷拍| 亚洲电影在线一区二区三区| 蜜桃导航-精品导航| 久久九九精品视频| 国产精品h在线观看| 久色国产在线| 日韩视频―中文字幕| 天堂资源中文在线| 日韩欧美国产1| 国产精品露脸视频| 精品国产电影一区| 欧美精品xxxxx| 中文字幕一区二区三区不卡在线| 在线观看福利片| 成+人+亚洲+综合天堂| 天天干天天曰天天操| 捆绑调教一区二区三区| 已婚少妇美妙人妻系列| 国产情侣一区| 欧美一级欧美一级| 97人人精品| 亚洲一区二区三区免费观看| 精品国产乱码久久久| 精品无人区一区二区三区竹菊| 91欧美日韩在线| 91色中文字幕| 欧美成人黄色| 国产精品久久久久久久久久免费| 蜜臀久久精品| 欧美国产中文字幕| 97超碰在线公开在线看免费| www.亚洲成人| 国产不卡在线| 大量国产精品视频| 超碰在线最新| 久久精品中文字幕电影| 欧美96在线| 精品国产一区二区三区久久久狼| 成人在线观看网站| 中文字幕欧美国内| 中文字幕在线免费| 夜夜躁日日躁狠狠久久88av| jizz亚洲| www.亚洲成人| 国产黄色在线免费观看| 萌白酱国产一区二区| 久cao在线| 欧美成人一区二区三区电影| 丝袜在线视频| 久久免费视频网| 不卡视频观看| 日韩美女写真福利在线观看| 欧美羞羞视频| 国产精品一久久香蕉国产线看观看| 粉嫩91精品久久久久久久99蜜桃 | 亚洲一区二区三区免费| 国产欧美日韩一区| 亚欧日韩另类中文欧美| 日韩精品欧美在线| 99久久久久| 国产成人一区二区三区别| 亚洲精品人人| 日本老熟妇毛茸茸| 精品一区二区在线视频| 香蕉视频在线观看黄| 99免费精品视频| 亚洲日本精品视频| 亚洲日本中文字幕区| 久久精品免费在线| 欧美午夜美女看片| 中文字幕在线观看视频一区| 日韩一级大片在线观看| 手机看片一区二区| 亚洲人成在线观| 菠萝菠萝蜜在线视频免费观看| 欧美精品18videosex性欧美| 日韩新的三级电影| 亚洲xxxxx| 亚洲三级网址| 色哺乳xxxxhd奶水米仓惠香| 亚洲精品专区| 日韩av.com| 99re这里只有精品视频首页| 久久久久久成人网| 亚洲综合偷拍欧美一区色| 在线观看 亚洲| 日韩限制级电影在线观看| 日韩电影免费| 欧美成人免费va影院高清| 电影一区二区三区| 亚洲在线免费视频| 国产精品欧美在线观看| 欧美大片免费播放| 丝袜亚洲另类欧美| 国产探花一区二区三区| 中文字幕高清一区| 日韩成人在线免费视频| 正在播放亚洲一区| 加勒比一区二区三区在线| 久久久久久久久久婷婷| 欧美在线se| 茄子视频成人在线观看| 最新成人av网站| 日本精品一区在线| 久久久国产一区二区三区四区小说 | 国产精品乱子久久久久| 日韩乱码一区二区| 在线成人av网站| 国产中文字幕在线观看| 久久免费视频网| 精品入口麻豆88视频| 视频一区二区三区在线观看 | 国产精品久久毛片av大全日韩| 日本一级黄色大片| 日韩视频在线你懂得| 免费观看久久久久| 国产精品v日韩精品| 全国精品免费看| 欧美久久在线观看| 国产成人在线免费| 男女做暖暖视频| 欧美日韩精品综合在线| 国产最新视频在线观看| 欧美又大粗又爽又黄大片视频| 永久免费精品视频| 中文字幕av久久| 久久av老司机精品网站导航| 亚洲av熟女国产一区二区性色| 午夜欧美大尺度福利影院在线看 | 亚洲毛片在线观看| 蜜桃视频m3u8在线观看| 国产一区高清视频| 亚洲高清在线| 久草视频福利在线| 亚洲主播在线播放| 成人毛片在线精品国产| 久久久久久久久中文字幕| 波多野结衣在线一区二区| 久久久天堂国产精品| 国产精品一区二区视频| 欧美三级免费看| 日韩小视频在线观看专区| 性欧美video高清bbw| 97人人香蕉| 亚洲青色在线| 捆绑裸体绳奴bdsm亚洲| 韩曰欧美视频免费观看| 欧美美乳在线| 日本欧美中文字幕| 欧美久久综合网| 日韩在线不卡一区| 亚洲欧美日本韩国| www.黄色片| 久久久久久香蕉网| 亚洲丁香日韩| 国产高清视频网站| 亚洲日本电影在线| 欧美少妇bbw| 国产91精品久久久| 精品产国自在拍| 美女在线视频一区二区| 亚洲男人天堂av| 女人18毛片水真多18精品| 51精品在线观看| 精品美女视频| 久久久久久综合网| 亚洲一区二区精品3399| 天天影院图片亚洲| 国产伦精品免费视频| 亚洲免费二区| 国产精品成人99一区无码| 色老综合老女人久久久| 求av网址在线观看| 国产精品10p综合二区| 亚洲综合不卡| 国产黄a三级三级| 欧美成人三级电影在线| 久久精品女人天堂av免费观看 | 最新国产在线观看| αv一区二区三区| 久久精品人人| 成人在线观看小视频| 亚洲精品福利在线观看| 成人亚洲网站| 99er在线视频| 国产人妖乱国产精品人妖| www.国产三级| 国产精品久久不能| 国产精品v日韩精品v欧美精品网站| 国产国语性生话播放| 欧美精品 国产精品| 国产精品25p| 中文字幕一区二区三区乱码| av网站一区二区三区| 91福利在线观看视频|