Spring-4-掌握Spring事務傳播機制

今日目標

能夠掌握Spring事務配置

Spring事務管理

1 Spring事務簡介【重點】

1.1 Spring事務作用

  • 事務作用:在數據層保障一系列的數據庫操作同成功同失敗

  • Spring事務作用:在數據層或業務層保障一系列的數據庫操作同成功同失敗

1.2 案例分析Spring事務

  • 需求:實現任意兩個賬戶間轉賬操作

  • 需求微縮:A賬戶減錢,B賬戶加錢

  • 分析: ①:數據層提供基礎操作,指定賬戶減錢(outMoney),指定賬戶加錢(inMoney) ②:業務層提供轉賬操作(transfer),調用減錢與加錢的操作 ③:提供2個賬號和操作金額執行轉賬操作 ④:基于Spring整合MyBatis環境搭建上述操作

  • 結果分析: ①:程序正常執行時,賬戶金額A減B加,沒有問題 ②:程序出現異常后,轉賬失敗,但是異常之前操作成功,異常之后操作失敗,整體業務失敗

  • 結構:

1.3 代碼實現

【前置工作】環境準備

創建數據庫和表

CREATE?DATABASE?IF?NOT?EXISTS?`spring_db2`?DEFAULT?CHARACTER?SET?utf8
USE?`spring_db2`;DROP?TABLE?IF?EXISTS?`tbl_account`;
CREATE?TABLE?`tbl_account`?(`id`?INT(11)?NOT?NULL?AUTO_INCREMENT,`name`?VARCHAR(20)?DEFAULT?NULL,`money`?DOUBLE?DEFAULT?NULL,PRIMARY?KEY?(`id`)
)?ENGINE=INNODB?AUTO_INCREMENT=3?DEFAULT?CHARSET=utf8;INSERT??INTO?`tbl_account`(`id`,`name`,`money`)?VALUES
(1,'Jack',1000),
(2,'Rose',1000);DROP?TABLE?IF?EXISTS?`tbl_log`;
CREATE?TABLE?`tbl_log`?(`id`?INT(11)?NOT?NULL?AUTO_INCREMENT,`info`?VARCHAR(255)?DEFAULT?NULL,`create_date`?DATETIME?DEFAULT?NULL,PRIMARY?KEY?(`id`)
)?ENGINE=INNODB?AUTO_INCREMENT=3?DEFAULT?CHARSET=utf8;INSERT??INTO?`tbl_log`(`id`,`info`,`create_date`)?VALUES
(2,'Jack向Rose轉賬520.0元','2021-11-04?17:19:18');

pom.xml添加依賴

????<dependencies><!--導入spring的坐標spring-context,對應版本是5.2.10.RELEASE--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.15</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.15</version></dependency>
<!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency><!--?https://mvnrepository.com/artifact/org.mybatis/mybatis?--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.13</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.0</version></dependency><!--?https://mvnrepository.com/artifact/com.alibaba/druid?--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.18</version></dependency><!--junit,spring對junit4的要求必須是4.12版本以上--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope></dependency><!--spring-test--><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.3.22</version><scope>test</scope></dependency></dependencies>

Spring整合Mybatis相關代碼(依賴、JdbcConfig、MybatisConfig、SpringConfig) JdbcConfig

package?com.zbbmeta.config;import?com.alibaba.druid.pool.DruidDataSource;
import?org.springframework.beans.factory.annotation.Value;
import?org.springframework.context.annotation.Bean;
import?org.springframework.context.annotation.Configuration;
import?org.springframework.jdbc.datasource.DataSourceTransactionManager;
import?org.springframework.transaction.PlatformTransactionManager;import?javax.sql.DataSource;public?class?JdbcConfig?{@Value("${jdbc.driverClassName}")private?String?driverClassName;@Value("${jdbc.url}")private?String?url;@Value("${jdbc.username}")private?String?userName;@Value("${jdbc.password}")private?String?password;@Beanpublic?DataSource?dataSource(){DruidDataSource?ds?=?new?DruidDataSource();ds.setDriverClassName(driverClassName);ds.setUrl(url);ds.setUsername(userName);ds.setPassword(password);return?ds;}//spring提供的事務切面類:里面增強了事務管理功能,里面有事務提交和事務回滾功能@Beanpublic?PlatformTransactionManager?transactionManager(DataSource?dataSource){DataSourceTransactionManager?ptm?=?new?DataSourceTransactionManager();ptm.setDataSource(dataSource);return?ptm;}
}

MybatisConfig

package?com.zbbmeta.config;import?org.apache.ibatis.logging.stdout.StdOutImpl;
import?org.apache.ibatis.session.Configuration;
import?org.mybatis.spring.SqlSessionFactoryBean;
import?org.mybatis.spring.mapper.MapperScannerConfigurer;
import?org.springframework.context.annotation.Bean;import?javax.sql.DataSource;public?class?MybatisConfig?{@Bean??//不僅可以將返回值加入IOC容器,而且可以實現方法參數進行依賴注入,參數默認會根據類型從IOC容器中獲取對象自動注入public?SqlSessionFactoryBean?sqlSessionFactoryBean(DataSource?dataSource){SqlSessionFactoryBean?ssfb?=?new?SqlSessionFactoryBean();ssfb.setTypeAliasesPackage("com.zbbmeta.entity");?//告訴mybatis,設置實體類包別名ssfb.setDataSource(dataSource);?//將IOC容器中連接池給到Mybatis//注意:必須導入org.apache.ibatis.session.Configuration;Configuration?configuration?=?new?Configuration();//設置整合mybatis駝峰命名映射configuration.setMapUnderscoreToCamelCase(true);//設置打印日志configuration.setLogImpl(StdOutImpl.class);ssfb.setConfiguration(configuration);return?ssfb;}
}

SpringConfig

@Configuration
@ComponentScan("com.zbbmeta")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
public?class?SpringConfig?{
}

Account

@ToString
@Data
public?class?Account?{private?Integer?id;private?String?name;private?Double?money;}

AccountDao

public?interface?AccountDao?{@Update("update?tbl_account?set?money?=?money?+?#{money}?where?name?=?#{name}")void?inMoney(@Param("name")?String?name,?@Param("money")?Double?money);@Update("update?tbl_account?set?money?=?money?-?#{money}?where?name?=?#{name}")void?outMoney(@Param("name")?String?name,?@Param("money")?Double?money);
}
public?interface?AccountService?{/***?轉賬操作*?@param?out?傳出方*?@param?in?轉入方*?@param?money?金額*/void?transfer(String?out,String?in,Double?money)?;
}

AccountServiceImpl

@Service
public?class?AccountServiceImpl?implements?AccountService?{@Autowiredprivate?AccountDao?accountDao;public?void?transfer(String?out,?String?in,?Double?money)?{//轉出accountDao.outMoney(out,?money);//模擬出現異常//System.out.println(1?/?0);//轉入accountDao.inMoney(in,?money);System.out.println("轉賬成功");}
}

【第一步】在業務層接口上添加Spring事務管理

在轉賬的方法上添加@Transactional注解

/***?業務接口*/
public?interface?AccountService?{/***?轉賬操作*?@param?out?傳出方*?@param?in?轉入方*?@param?money?金額*/@Transactionalvoid?transfer(String?out,String?in?,Double?money)?;
}

注意事項

  1. Spring注解式事務通常添加在業務層接口中而不會添加到業務層實現類中,降低耦合

  2. 注解式事務可以添加到業務方法上表示當前方法開啟事務,也可以添加到接口上表示當前接口所有方法開啟事務

【第二步】設置事務管理器(將事務管理器添加到IOC容器中)

說明:可以在JdbcConfig中配置事務管理器

//配置事務管理器,mybatis使用的是jdbc事務
@Bean
public?PlatformTransactionManager?transactionManager(DataSource?dataSource){DataSourceTransactionManager?transactionManager?=?new?DataSourceTransactionManager();transactionManager.setDataSource(dataSource);return?transactionManager;
}

注意事項

  1. 事務管理器要根據實現技術進行選擇

  2. MyBatis框架使用的是JDBC事務

【第三步】開啟注解式事務驅動

@EnableTransactionManagement

@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
@EnableTransactionManagement?//開啟事務注解掃描
public?class?SpringConfig?{
}

【第四步】運行測試類,查看結果

  1. 去掉@EnableTransactionManagement注解,即沒有進行事務管理,當轉賬出現問題時結果

  1. 加上@EnableTransactionManagement注解,賬戶錢都恢復成1000

結果

  1. 轉賬成功的時候

結果:

@RunWith(SpringJUnit4ClassRunner.class)??//指定第三方的運行器
@ContextConfiguration(classes?=?SpringConfig.class)??//讀取類配置文件
public?class?AccountDaoTest?{@Autowired??//自動注入業務對象private?AccountService?accountService;@Testpublic?void?testFindById()?throws?IOException?{//直接使用業務方法accountService.transfer("Jack","Rose",?100d);}
}

2 Spring事務角色【理解】

問題導入

什么是事務管理員,什么是事務協調員?

2.1 Spring事務角色

  • 事務管理員:發起事務方,在Spring中通常指代業務層開啟事務的方法

  • 事務協調員:加入事務方,在Spring中通常指數據層方法,也可以是業務層方法

3 Spring事務相關配置

問題導入

什么樣的異常,Spring事務默認是不進行回滾的?

3.1 @Transactional注解中與事務相關配置

屬性作用示例
readOnly設置是否為只讀事務readOnly=true 只讀事務
timeout設置事務超時時間timeout = -1(永不超時)
rollbackFor設置事務回滾異常(class)rollbackFor = {FileNotFoundException.class}
rollbackForClassName設置事務回滾異常(String)同上格式為字符串
noRollbackFor設置事務不回滾異常(class)noRollbackFor = {FileNotFoundException.class}
noRollbackForClassName設置事務不回滾異常(String)同上格式為字符串
propagation設置事務傳播行為……
屬性作用示例
readOnly設置是否為只讀事務readOnly=true 只讀事務
timeout設置事務超時時間timeout = -1(永不超時)
rollbackFor設置事務回滾異常(class)rollbackFor = {FileNotFoundException.class}
rollbackForClassName設置事務回滾異常(String)同上格式為字符串
noRollbackFor設置事務不回滾異常(class)noRollbackFor = {FileNotFoundException.class}
noRollbackForClassName設置事務不回滾異常(String)同上格式為字符串
propagation設置事務傳播行為……

說明:對于RuntimeException類型異常或者Error錯誤,Spring事務能夠進行回滾操作。但是對于非運行時異常,Spring事務是不進行回滾的,所以需要使用rollbackFor來設置要回滾的異常。

3.2 案例:轉賬業務追加日志

需求和分析

  • 需求:實現任意兩個賬戶間轉賬操作,并對每次轉賬操作在數據庫進行記錄

  • 需求微縮:A賬戶減錢,B賬戶加錢,數據庫記錄日志

  • 分析: ①:基于轉賬操作案例添加日志模塊,實現數據庫中記錄日志 ②:業務層轉賬操作(transfer),調用減錢、加錢與記錄日志功能

  • 實現效果預期: 無論轉賬操作是否成功,均進行轉賬操作的日志留痕

  • 存在的問題: 日志的記錄與轉賬操作隸屬同一個事務,同成功同失敗

  • 實現效果預期改進: 無論轉賬操作是否成功,日志必須保留

  • 事務傳播行為:事務協調員對事務管理員所攜帶事務的處理態度

【準備工作】環境整備

創建新的LogDao接口

public?interface?LogDao?{@Insert("insert?into?tbl_log?(info,create_date)?values(#{info},now())")void?log(String?info);
}

創建業務接口使用事務

public?interface?LogService?{/***?記錄日志*?@param?out?轉出賬戶*?@param?in?轉入賬戶*?@param?money?金額*?設置事務屬性:傳播行為設置為需要新事務*/@Transactionalvoid?log(String?out,?String?in,?Double?money);
}

實現類

@Service
public?class?LogServiceImpl?implements?LogService?{@Autowiredprivate?LogDao?logDao;public?void?log(String?out,?String?in,?Double?money)?{logDao.log("轉賬操作由"?+?out?+?"到"?+?in?+?",金額:"?+?money);}
}

【第一步】在AccountServiceImpl中調用logService中添加日志的方法

因為無論成功與否,都需要記錄日志,所以日志放在finally語句塊中,但異常不需要捕獲,要拋出用來激活事務的處理

/***?業務接口*/
public?interface?AccountService?{/***?轉賬操作*?@param?out?傳出方*?@param?in?轉入方*?@param?money?金額*/@Transactionalvoid?transfer(String?out,String?in?,Double?money)?;
}
@Service
public?class?AccountServiceImpl?implements?AccountService?{@Autowiredprivate?AccountDao?accountDao;@Autowiredprivate?LogService?logService;public?void?transfer(String?out,String?in?,Double?money)?{try{accountDao.outMoney(out,money);//int?i?=?1/0;accountDao.inMoney(in,money);}?finally?{logService.log(out,in,money);}}
}

【第二步】在LogService的log()方法上設置事務的傳播行為

需求:無論有沒有異常日志都要記錄下來,不能被回滾

  1. 先只設置@Transactional,查看運行結果

  2. 設置成當前操作需要新事務再查看運行結果

public?interface?LogService?{//propagation設置事務屬性:傳播行為設置為當前操作需要新事務@Transactional(propagation?=?Propagation.REQUIRES_NEW)void?log(String?out,?String?in,?Double?money);
}

【第三步】運行測試類,查看結果

@RunWith(SpringJUnit4ClassRunner.class)??//指定第三方的運行器
@ContextConfiguration(classes?=?SpringConfig.class)??//讀取類配置文件
public?class?AccountServiceTest?{@Autowired??//自動注入業務對象private?AccountService?accountService;/***?轉賬的測試*/@Testpublic?void?testTransfer()?{accountService.transfer("Jack",?"Rose",?10d);}
}

思考:為什么 在LogService的方法上設置propagation = Propagation.REQUIRES_NEW接可以創建新的事務?

這就是事務傳播行為(經常會面試提問)

3.3 事務傳播行為

傳播屬性Method1Method2
REQUIRED開啟TI事務加入T1事務
新建T2事務
REQUIRES_NEW開啟TI事務新建T2事務
新建T2事務
SUPPORTS開啟TI事務加入T1事務
NOT_SUPPORTED開啟TI事務
MANDATORY開啟TI事務加入T1事務
ERROR
NEVER開啟TI事務ERROR
NESTED

思考:事務會一直生效?有沒有事務失效的情況?為什么會失效,大家可以思考一下,這也是一個長問面試題

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

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

相關文章

STM32--TIM定時器(2)

文章目錄 輸出比較PWM輸出比較通道參數計算舵機簡介直流電機簡介TB6612 PWM基本結構PWM驅動呼吸燈PWM驅動舵機PWM控制電機 輸出比較 輸出比較&#xff0c;簡稱OC&#xff08;Output Compare&#xff09;。 輸出比較的原理是&#xff0c;當定時器計數值與比較值相等或者滿足某種…

【數據結構OJ題】有效的括號

原題鏈接&#xff1a;https://leetcode.cn/problems/valid-parentheses/ 目錄 1. 題目描述 2. 思路分析 3. 代碼實現 1. 題目描述 2. 思路分析 這道題目主要考查了棧的特性&#xff1a; 題目的意思主要是要做到3點匹配&#xff1a;類型、順序、數量。 題目給的例子是比較…

【Hibench 】完成 HDP-Spark 性能測試

&#x1f341; 博主 "開著拖拉機回家"帶您 Go to New World.?&#x1f341; &#x1f984; 個人主頁——&#x1f390;開著拖拉機回家_Linux,Java基礎學習,大數據運維-CSDN博客 &#x1f390;?&#x1f341; &#x1fa81;&#x1f341; 希望本文能夠給您帶來一定的…

單片機實訓報告

這周我們進行了單片機實訓&#xff0c;一周中我們通過七個項目1&#xff1a;P1 口輸入/輸出 2&#xff1a;繼電器控制 3 音頻控制 4&#xff1a;子程序設計 5&#xff1a;字符碰頭程序設計 6&#xff1a;外部中斷 7&#xff1a; 急救車與交通信號燈&#xff0c;練習編寫了子程…

mysql 設置 mysql 日志時間與系統時間保持一致

臨時設置 mysql> show variables like %log_timestamps%;-----------------------| Variable_name | Value |-----------------------| log_timestamps | UTC |-----------------------1 row in set (0.00 sec)系統是 CST &#xff0c; nysql 是 UTC當UTC時間為0點時&am…

docker的使用方法總結

Docker是一個非常強大的工具&#xff0c;它可以用于創建、部署和運行應用程序。以下是一些docker相關的常用指令&#xff0c; 1、查看docker版本 docker version 2、查看正在運行的Docker容器 docker ps 3、查看所有的docker容器&#xff08;包括沒有運行的容器&#xff0…

Python 之 Http 獲取網頁的 html 數據,并去掉 html 格式等相關信息

Python之 Http 獲取網頁的 html 數據,并去掉 html 格式等相關信息 目錄 Python之 Http 獲取網頁的 html 數據,并去掉 html 格式等相關信息

SCF金融公鏈新加坡啟動會 創新驅動未來

新加坡迎來一場引人矚目的金融科技盛會&#xff0c;SCF金融公鏈啟動會于2023年8月13日盛大舉行。這一受矚目的活動將為金融科技領域注入新的活力&#xff0c;并為廣大投資者、合作伙伴以及關注區塊鏈發展的人士提供一個難得的交流平臺。 在SCF金融公鏈啟動會上&#xff0c; Wil…

級聯(數據字典)

二級級聯&#xff1a; 一&#xff1a;新建兩個Bean 父級&#xff1a; /*** Description 數據字典* Author WangKun* Date 2023/7/25 10:15* Version*/ Data AllArgsConstructor NoArgsConstructor TableName("HW_DICT_KEY") public class DictKey implements Seri…

excel快速選擇數據、選擇性粘貼、凍結單元格

一、如何快速選擇數據 在excel中&#xff0c;希望選擇全部數據&#xff0c;通常使用鼠標選擇數據然后往下拉&#xff0c;當數據很多時&#xff0c;也可單擊單元格使用ctrl A選中全部數據&#xff0c;此外&#xff0c;具體介紹另一種方法。 操作&#xff1a;ctrl shift 方向…

【C++】STL---list

STL---list 一、list 的介紹二、list 的模擬實現1. list 節點類2. list 迭代器類&#xff08;1&#xff09;前置&#xff08;2&#xff09;后置&#xff08;3&#xff09;前置- -、后置- -&#xff08;4&#xff09;! 和 運算符重載&#xff08;5&#xff09;* 解引用重載 和 …

css3新增屬性

文章目錄 css3新增屬性box-shadowborder-radius設置橢圓 position: sticky;漸變背景線性漸變可重復的漸變背景 徑向漸變可重復的漸變背景 過渡分屬性 動畫關鍵幀與transition的關系demo 變形平移使用 旋轉使用 其他使用立體效果perspective元素位于3D空間還是平面中 縮放變形的…

tornado在模板中遍歷二維數組

要在Tornado模板中遍歷一個二維數組&#xff0c;你可以使用Tornado的模板語法來實現迭代和顯示數組中的每個元素。 以下是一個示例&#xff0c;演示如何在Tornado模板中遍歷和顯示二維數組的內容&#xff1a; template.html: <!DOCTYPE html> <html> <head&g…

小米分享 | 解密面試題:網易面試如何回答“創建線程有哪幾種方式?”

大家好&#xff0c;我是你們的小米&#xff01;今天要和大家一起探討一個在技術面試中常見的問題&#xff1a;創建線程有哪幾種方式&#xff1f;這可是個經典面試題哦&#xff01;不過別擔心&#xff0c;小米在這里為你詳細解析&#xff0c;幫你輕松應對&#xff0c;讓你在面試…

深度學習在MRI運動校正中的應用綜述

運動是MRI中的主要挑戰之一。由于MR信號是在頻率空間中獲取的&#xff0c;因此除了其他MR成像偽影之外&#xff0c;成像對象的任何運動都會導致重建圖像中產生偽影。深度學習被提出用于重建過程的幾個階段的運動校正。廣泛的MR采集序列、感興趣的解剖結構和病理學以及運動模式&…

用dcker極簡打包java.jar鏡像并啟動

用dcker極簡打包java.jar鏡像并啟動 一、本地打包好jar包 二、新建文件夾&#xff0c;將步驟1中的jar包拷貝到文件夾下 三、同目錄下新建Dockerfile ## 基礎鏡像&#xff0c;這里用的是openjdk:8 FROM openjdk:8## 將步驟一打包好的jar包 拷貝到鏡像的 跟目錄下[目錄可以自定義…

Oracle字段長度不足位數補零

Oracle字段長度不足位數補零 有時候從數據庫中取出的月份值是1&#xff0c;而不是01&#xff0c;該怎么辦呢 SELECTLPAD( CODE_MONTH, 2, 0 ) FROMtb_cube_TY001 WHERECODE_BM_MEATYPE TY20 AND code_measure MYLX01 AND code_month <> ~ AND CODE_ENTITY 01A AND…

【實戰】十一、看板頁面及任務組頁面開發(二) —— React17+React Hook+TS4 最佳實踐,仿 Jira 企業級項目(二十四)

文章目錄 一、項目起航&#xff1a;項目初始化與配置二、React 與 Hook 應用&#xff1a;實現項目列表三、TS 應用&#xff1a;JS神助攻 - 強類型四、JWT、用戶認證與異步請求五、CSS 其實很簡單 - 用 CSS-in-JS 添加樣式六、用戶體驗優化 - 加載中和錯誤狀態處理七、Hook&…

“深入探索JVM:解析Java虛擬機的工作原理與優化“

標題&#xff1a;深入探索JVM&#xff1a;解析Java虛擬機的工作原理與優化 摘要&#xff1a;本篇博客將深入探討Java虛擬機&#xff08;JVM&#xff09;的工作原理以及如何優化JVM的性能。我們將介紹JVM的組成部分、類加載過程、內存管理、垃圾回收機制以及常見的性能優化技術…

記一次線上OOM事故

OOM 問題 linux內核有個機制叫OOM killer(Out-Of-Memory killer)&#xff0c;當系統需要申請內存卻申請不到時&#xff0c;OOM killer會檢查當前進程中占用內存最大者&#xff0c;將其殺掉&#xff0c;騰出內存保障系統正常運行。 一般而言&#xff0c;一個應用的內存逐漸增加&…