使用@Transactional 注解下,事務失效的場景

前言

@Transactional是一種基于注解管理事務的方式,spring通過動態代理的方式為目標方法實現事務管理的增強。

@Transactional使用起來方便,但也需要注意引起@Transactional失效的場景,本文總結了七種情況,下面進行逐一分析。

一、異常被捕獲后沒有拋出

當異常被捕獲后,并且沒有再拋出,那么deleteUserA是不會回滾的。

@Transactional
public void deleteUser() {userMapper.deleteUserA();try {int i = 1 / 0;userMapper.deleteUserB();} catch (Exception e) {e.printStackTrace();}
}

二、拋出非運行時異常

Spring 事務,默認情況下只會回滾RuntimeException(運行時異常)和Error(錯誤),對于普通的 Exception(非運行時異常),它不會回滾。

@Transactional
public void deleteUser() throws MyException{userMapper.deleteUserA();try {int i = 1 / 0;userMapper.deleteUserB();} catch (Exception e) {throw new MyException();}
}

如果事務注解使用的是@Transactional(rollbackFor = Exception.class),那么拋出的是非RuntimeException類型異常是可以回滾的。

@Transactional(rollbackFor = Exception.class)

三、方法內部直接調用

這種場景很常見,方法A調用方法B,其中方法A未使用事務,而方法B使用了事務,此時方法B的事務是不生效的。例子如下,如果先調用deleteUser(),那么deleteUserA()是不會回滾的,其原因就是@Transactional根本沒生成代理,如果直接調用deleteUser2()那么沒問題,deleteUserA()會回滾。?

@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public void deleteUser() throws MyException{deleteUser2();}@Transactionalpublic void deleteUser2() throws MyException{userMapper.deleteUserA();int i = 1 / 0;userMapper.deleteUserB();}
}

1. 修改調用方式,把當前類自己注入一下調用即可。

@Service
public class UserService {@Autowiredprivate UserMapper userMapper;//自己注入自己@AutowiredUserService userService;public void deleteUser() throws MyException{userService.deleteUser2();}@Transactionalpublic void deleteUser2() throws MyException{userMapper.deleteUserA();int i = 1 / 0;userMapper.deleteUserB();}
}

2. 新加一個service方法,只需要新加一個 Service 方法,把 @Transactional 注解加到新 Service 方法上,把需要事務執行的代碼移到新方法中

@Servcie
public class ServiceA {@Autowiredprvate ServiceB serviceB;public void save(User user) {queryData1();queryData2();serviceB.doSave(user);}}@Servciepublic class ServiceB {@Transactional(rollbackFor=Exception.class)public void doSave(User user) {addData1();updateData2();}}

四、新開啟一個線程

如下的方式deleteUserA()也不會回滾,因為spring實現事務的原理是通過ThreadLocal把數據庫連接綁定到當前線程中,新開啟一個線程獲取到的連接就不是同一個了。

@Transactional
public void deleteUser() throws MyException{userMapper.deleteUserA();try {//休眠1秒,保證deleteUserA先執行Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}new Thread(() -> {int i = 1/0;userMapper.deleteUserB();}).start();    
}

五、訪問權限問題

java 的訪問權限主要有四種:private、default、protected、public,它們的權限從左到右,依次變大。如果方法的訪問權限被定義成了private,這樣會導致事務失效,spring 要求被代理方法必須是public的。

@Transactional
private void deleteUser() throws MyException{userMapper.deleteUserA();int i = 1/0;userMapper.deleteUserB();
}

六、方法被final修飾

spring 事務底層使用了 aop,也就是通過 jdk 動態代理或者 cglib,幫我們生成了代理類,在代理類中實現的事務功能。但如果某個方法用 final 修飾了,那么在它的代理類中,就無法重寫該方法,而添加事務功能。

@Transactional
public final void deleteUser() throws MyException{userMapper.deleteUserA();int i = 1/0;userMapper.deleteUserB();
}

注意:如果某個方法是 static修飾的,同樣無法通過動態代理,變成事務方法。?

七、數據庫本身不支持

在 mysql5 之前,默認的數據庫引擎是myisam。它的缺點就是不支持事務,因此在mysql5之后,必須設置數據庫引擎為InnoDB。

八、未被Spring管理

在我們平時開發過程中,有個細節很容易被忽略,即使用 spring 事務的前提是:對象要被 spring 管理,需要創建 bean 實例。通常情況下,我們通過 @Controller、@Service、@Component、@Repository 等注解,可以自動實現 bean 實例化和依賴注入的功能。如果有一天,你匆匆忙忙地開發了一個 Service 類,但忘了加 @Service 注解,那么該類不會交給 spring 管理,所以它內部的方法也不會生成事務。

九、事務傳播屬性設置錯誤

我們在使用@Transactional注解時,是可以指定propagation參數的。
該參數的作用是指定事務的傳播特性,spring 目前支持 7 種傳播特性:

REQUIRED 如果當前上下文中存在事務,則加入該事務,如果不存在事務,則創建一個事務,這是默認的傳播屬性值。
SUPPORTS 如果當前上下文中存在事務,則支持事務加入事務,如果不存在事務,則使用非事務的方式執行。
MANDATORY 當前上下文中必須存在事務,否則拋出異常。
REQUIRES_NEW 每次都會新建一個事務,并且同時將上下文中的事務掛起,執行當前新建事務完成以后,上下文事務恢復再執行。
NOT_SUPPORTED 如果當前上下文中存在事務,則掛起當前事務,然后新的方法在沒有事務的環境中執行。
NEVER 如果當前上下文中存在事務,則拋出異常,否則在無事務環境上執行代碼。
NESTED 如果當前上下文中存在事務,則嵌套事務執行,如果不存在事務,則新建事務。
目前只有這三種傳播特性才會創建新事務:REQUIRED,REQUIRES_NEW,NESTED。設置其他傳播特性都不會創建事務。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/17146.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/17146.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/17146.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【面試必看】Java并發

并發 1. 線程 1. 線程vs進程 進程是程序的一次執行過程,是系統運行程序的基本單位,因此進程是動態的。 系統運行一個程序即是一個進程從創建,運行到消亡的過程。在 Java 中,當我們啟動 main 函數時其實就是啟動了一個 JVM 的進…

ChaosMeta V0.7.0 版本發布 進入CNCF混沌工程全景圖

混沌工程 ChaosMeta 的全新版本 V0.7.0 現已正式發布!該版本包含了許多新特性和增強功能,在編排界面提供了多集群管理,在代碼層面支持多命令下發通道的選擇。另外由螞蟻集團發起的ChaosMeta于北京時間2024年1月10日正式進入CNCF混沌工程全景圖…

20232906 2023-2024-2 《網絡與系統攻防技術》第十一次作業

20232906 2023-2024-2 《網絡與系統攻防技術》第十一次作業 1.實驗內容 一、web瀏覽器滲透攻擊 任務:使用攻擊機和Windows靶機進行瀏覽器滲透攻擊實驗,體驗網頁木馬構造及實施瀏覽器攻擊的實際過程。 二、取證分析實踐—網頁木馬攻擊場景分析 ①首先你…

07_Servlet

Servlet 一 Servlet簡介 1.1 動態資源和靜態資源 靜態資源 無需在程序運行時通過代碼運行生成的資源,在程序運行之前就寫好的資源. 例如:html css js img ,音頻文件和視頻文件 動態資源 需要在程序運行時通過代碼運行生成的資源,在程序運行之前無法確定的數據,運行時動態生成…

轉行一年了

關注、星標公眾號,直達精彩內容 ID:技術讓夢想更偉大 整理:李肖遙 來公司一年了。 說是轉行其實還是在半導體行業,熟悉我的朋友知道 ,我在18年開始進入半導體行業,那個時候想著行業很重要,站對了…

【前端三劍客之JS】詳解JS

1. JS的引入方式 (1). 內部腳本方式引入 在頁面上,通過一對script標簽引入js代碼.script代碼放置位置有一定隨意性,一般放在head標簽中. (2).外部腳本方式引入. 內部腳本只能在當前頁面中使用,代碼復用度不高.可以將腳本放在單獨的js文件…

HG/T 6088-2022 透水道路用涂料檢測

透水混凝土是指由水泥、礦物摻合料、骨料、外加劑及水等主要材料經拌合形成的,具有透水功能的混凝土材料,用于其表面的涂料稱為透水道路用涂料。 HG/T 6088-2022透水道路用涂料檢測項目: 測試指標 測試方法 有害物質限量 GB 38468 在容器…

io.net 是什么,DePIN(去中心化物理基礎設施網絡)

目錄 io.net 是什么 io.net去中心化原理 DePIN(去中心化物理基礎設施網絡)

氣泡水位計的安裝方法詳解(二)

氣泡水位計的安裝方法詳解(二) 產品簡介 氣泡式水位計ZL-BWL-013是一款適用于水文、水利信息化建設領域的新一代水位測量類設備,產品執行GB/T 11828.2-2022標準。ZL-BWL-013氣泡水位計,具有安裝方便、易于操作,高精度…

算法刷題day54:搜索(一)

目錄 引言一、池塘計數二、城堡問題三、山峰和山谷四、迷宮問題五、武士風度的牛六、抓住那頭牛七、矩陣距離八、魔板 引言 針對于藍橋杯,搜索問題還是非常之重要的,在省賽前深知暴搜的重要性,所以提前先把提高課的搜索一章給看了&#xff0…

odoo10 編寫圖片上傳接口(獲取外部訪問鏈接)

首先你需要一個模型 class Vehicle(models.Model):_name vehicleimage fields.Binary(string"圖片", attachmentTrue)編寫圖片訪問接口 http.route(/vehicle/image/<int:vehicle_id>, typehttp, authpublic)def vehicle_image(self, vehicle_id, **kwargs)…

分布式鎖的原理和實現(Go)

文章目錄 為什么需要分布式鎖&#xff1f;go語言分布式鎖的實現Redis自己的實現紅鎖是什么別人的帶紅鎖的實現 etcdzk的實現 為什么需要分布式鎖&#xff1f; 保證分布式系統并發請求或不同服務實例操作共享資源的安全性&#xff0c;通過一種協調機制來保證在同一時刻只有一個…

設計模式17——模板方法模式

寫文章的初心主要是用來幫助自己快速的回憶這個模式該怎么用&#xff0c;主要是下面的UML圖可以起到大作用&#xff0c;在你學習過一遍以后可能會遺忘&#xff0c;忘記了不要緊&#xff0c;只要看一眼UML圖就能想起來了。同時也請大家多多指教。 模板方法模式&#xff08;Temp…

阿里云Linux 3.2104 LTS 64位安裝SVN服務器

直接按步驟 yum install subversion 寫y就行 主要是看看安裝了那些文件 rpm -ql subversion 主要是為了創建版本庫而準備&#xff0c;這個能一遍創建就一遍創建&#xff0c;不行就逐個創建。能創就忽略下面兩個mkdir步驟。 mkdir /home/svn/groupRepos 根據新建目錄作為版本…

LeetCode第131場雙周賽C++題解

3158.求出出現兩次數字的XOR值 給你一個數組 nums &#xff0c;數組中的數字 要么 出現一次&#xff0c;要么 出現兩次。 請你返回數組中所有出現兩次數字的按位 XOR 值&#xff0c;如果沒有數字出現過兩次&#xff0c;返回 0 。 示例 1&#xff1a; 輸入&#xff1a;nums …

程序中的網絡地址等敏感信息,從網絡安全的角度,應該怎么配置

從網絡安全的角度來看&#xff0c;配置IP信息需要謹慎處理&#xff0c;以防止敏感信息泄露和系統受到攻擊。以下是一些建議和最佳實踐&#xff1a; 1. 使用環境變量或配置管理工具 環境變量 將IP地址等敏感信息存儲在環境變量中&#xff0c;而不是硬編碼在代碼里。這有助于確…

業務實戰————Uibot6.0 .1多頁面商品信息抓取RPA機器人

前言 【案例描述】 鮮果記水果店計劃在淘寶電商平臺上開設一家新店&#xff0c;小微是該企業運營部分的運營專員&#xff0c;主要負責公司商品上架和管理的工作。 公司計劃在開店的新品促銷活動中增加水果品類紅富士蘋果。小微需在商品上架前了解目前平臺中銷量前列的紅富士蘋…

C#面:死鎖的必要條件是什么?怎么克服?

C#中的死鎖是指兩個或多個線程互相等待對方釋放資源&#xff0c;導致程序無法繼續執行的情況。 死鎖的必要條件&#xff1a; 互斥條件&#xff1a;至少有一個資源被設置為只能被一個線程占用。請求與保持條件&#xff1a;一個線程在持有資源的同時又請求其他線程占有的資源。…

SpringBootTest測試框架一

為了方便開發,對數據進行mock處理,形成文件,只修改文件內容達到mock指定數據的目的 1、定義測試模式 @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface TestModel {TestModelEnum value() default TestModelEnum.LOCAL_PRIOR;String…

數字水印 | 離散余弦變換 DCT 基本原理及 Python 代碼實現

目錄 1?基本原理2?代碼實現3?圖像壓縮 1?基本原理 參考博客&#xff1a;https://www.cnblogs.com/zxporz/p/16072580.html D C T \mathsf{DCT} DCT 全稱為 D i s c r e t e C o s i n e T r a n s f o r m \mathsf{Discrete\ Cosine\ Transform} Discrete Cosine Transfo…