欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring聲明式事務(wù)@Transactional的用法解讀

 更新時間:2025年05月06日 09:03:16   作者:棕豆兔&  
這篇文章主要介紹了Spring聲明式事務(wù)@Transactional的用法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

Spring 聲明式事務(wù) @Transactional的使用很簡單,只需要添加依賴,在需要的方法或者類上添加 @Transactional注解即可。

一、添加依賴

<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-tx</artifactId>
</dependency>

在需要事務(wù)的方法上添加 @Transactional 注解就可以實現(xiàn)了,無需手動開啟事務(wù)和提交事務(wù),進(jìn)入方法時自動開啟事務(wù),方法執(zhí)行完會自動提交事務(wù),如果中途發(fā)生了沒有處理的異常會自動回滾事務(wù)。

代碼示例:

@RequestMapping("/trans")
@RestController
public class TransactionalController {

 @Autowired
 private UserService userService;

 @Transactional
 @RequestMapping("/registry")
 public String registry(String name,String password){
 //用戶注冊
 userService.registryUser(name,password);
 return "注冊成功";
 }
}

假設(shè)代碼有異常:

@Slf4j
@RequestMapping("/trans")
@RestController
public class TransactionalController {

 @Autowired
 private UserService userService;

 @Transactional
 @RequestMapping("/registry")
 public String registry(String name,String password){
 //?戶注冊
 userService.registryUser(name,password);
 log.info("用戶數(shù)據(jù)插?成功");
 //強(qiáng)制程序拋出異常
 int a = 10/0;
 return "注冊成功";
 }
}

啟動項目發(fā)現(xiàn)雖然日志顯示數(shù)據(jù)插入成功,但數(shù)據(jù)庫卻沒有新增數(shù)據(jù),事務(wù)進(jìn)行了回滾。

二、@Transactional 作用

@Transactional 可以用來修飾方法或類:

  • 修飾方法時: 只有修飾public 方法時才生效(修飾其他方法時不會報錯, 也不生效)[推薦]
  • 修飾類時: 對 @Transactional 修飾的類中所有的 public 方法都生效。

方法/類被 @Transactional 注解修飾時,在目標(biāo)方法執(zhí)行開始之前,會自動開啟事務(wù),方法執(zhí)行結(jié)束之后,自動提交事務(wù)。

  • 如果在方法執(zhí)行過程中,出現(xiàn)異常,且異常未被捕獲,就進(jìn)行事務(wù)回滾操作。
  • 如果異常被程序捕獲,方法就被認(rèn)為是成功執(zhí)行,依然會提交事務(wù)。

舉例:(對異常進(jìn)行捕獲)

@Transactional
@RequestMapping("/registry")
public String registry(String name,String password){
 //??注冊
 userService.registryUser(name,password);
 log.info("??數(shù)據(jù)插?成功");
 //對異常進(jìn)?捕獲
 try {
 //強(qiáng)制程序拋出異常
 int a = 10/0;
 }catch (Exception e){
 e.printStackTrace();
 }
 return "注冊成功";
}

運行程序,發(fā)現(xiàn)雖然程序出錯了,但是由于異常被捕獲,所以事務(wù)依然得到了提交。

如果需要事務(wù)進(jìn)行回滾,有以下兩種方式:

  • 重新拋出異常
@Transactional
@RequestMapping("/registry")
public String registry(String name,String password){
//?戶注冊
userService.registryUser(name,password);
log.info("??數(shù)據(jù)插?成功");
 //對異常進(jìn)?捕獲
 try {
 //強(qiáng)制程序拋出異常
 int a = 10/0;
 }catch (Exception e){
 //將異常重新拋出去
 throw e;
 }
 return "注冊成功";
}
  • 手動回滾事務(wù)

使用TransactionAspectSupport.currentTransactionStatus() 得到當(dāng)前的事務(wù),并使用用 setRollbackOnly 設(shè)置 setRollbackOnly。

@Transactional
@RequestMapping("/registry")
public String registry(String name,String password){
//?戶注冊
userService.registryUser(name,password);
log.info("?戶數(shù)據(jù)插?成功");
//對異常進(jìn)行捕獲
try {
//強(qiáng)制程序拋出異常
int a = 10/0;
}catch (Exception e){
// 手動回滾事務(wù)
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
return "注冊成功";
}

三、@Transactional詳解

@Transactional注解有三個常見的屬性:

  • rollbackFor: 異?;貪L屬性。指定能夠觸發(fā)事務(wù)回滾的異常類型,可以指定多個異常類型。
  • isolation: 事務(wù)的隔離級別。默認(rèn)值為 Isolation.DEFAULT
  • propagation: 事務(wù)的傳播機(jī)制。默認(rèn)值為 Propagation.REQUIRED

3.1 rollbackFor

@Transactional 默認(rèn)只在遇到運行時異常和Error時才會回滾,非運行時異常不回滾。即

Exception的子類中,除了RuntimeException及其子類。

如果需要所有異常都回滾,需要來配置 @Transactional 注解當(dāng)中的 rollbackFor 屬性,通過rollbackFor 這個屬性指定出現(xiàn)何種異常類型時事務(wù)進(jìn)行回滾。

@Transactional(rollbackFor = Exception.class)
@RequestMapping("/r2")
public String r2(String name,String password) throws IOException {

 //?戶注冊
 userService.registryUser(name,password);
 log.info("?戶數(shù)據(jù)插?成功");
 if (true){
 throw new IOException();
 }
 return "r2";
}

運行程序會發(fā)現(xiàn)雖然程序拋出了異常,但是事務(wù)依然進(jìn)行了提交。

3.2 事務(wù)隔離級別

事務(wù)隔離級別解決的是多個事務(wù)同時調(diào)用一個數(shù)據(jù)庫的問題:

Spring 中事務(wù)隔離級別有 5 種:

  • Isolation.DEFAULT : 以連接的數(shù)據(jù)庫的事務(wù)隔離級別為主;
  • Isolation.READ_UNCOMMITTED : 讀未提交,對應(yīng)SQL標(biāo)準(zhǔn)中 READ UNCOMMITTED;
  • Isolation.READ_COMMITTED : 讀已提交,對應(yīng)SQL標(biāo)準(zhǔn)中 READ COMMITTED;
  • Isolation.REPEATABLE_READ : 可重復(fù)讀,對應(yīng)SQL標(biāo)準(zhǔn)中 REPEATABLE READ;
  • Isolation.SERIALIZABLE : 串行化,對應(yīng)SQL標(biāo)準(zhǔn)中 SERIALIZABLE。
public enum Isolation {
 DEFAULT(-1),
 READ_UNCOMMITTED(1),
 READ_COMMITTED(2),
 REPEATABLE_READ(4),
 SERIALIZABLE(8);
 private final int value;
 private Isolation(int value) {
 this.value = value;
 }
 public int value() {
 return this.value;
 }
}

Spring 中事務(wù)隔離級別可以通過 @Transactional 中的 isolation 屬性進(jìn)行設(shè)置:

@Transactional(isolation = Isolation.READ_COMMITTED)
@RequestMapping("/r3")
public String r3(String name,String password) throws IOException {
 //... 
 return "r3";
}

3.3 Spring 事務(wù)傳播機(jī)制

事務(wù)傳播機(jī)制就是: 多個事務(wù)方法存在調(diào)用關(guān)系時,事務(wù)是如何在這些方法間進(jìn)行傳播的。

事務(wù)傳播機(jī)制解決的是一個事務(wù)在多個節(jié)點(方法)中傳遞的問題:

@Transactional 注解支持事務(wù)傳播機(jī)制的設(shè)置, 通過 propagation 屬性來指定傳播行為。

Spring 事務(wù)傳播機(jī)制有以下 7 種:

  • Propagation.REQUIRED:默認(rèn)的事務(wù)傳播級別。如果當(dāng)前存在事務(wù), 則加入該事務(wù)。如果當(dāng)前沒有事務(wù),則創(chuàng)建一個新的事務(wù).
  • Propagation.SUPPORTS:如果當(dāng)前存在事務(wù),則加入該事務(wù)。如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運行。
  • Propagation.MANDATORY:強(qiáng)制性。如果當(dāng)前存在事務(wù), 則加入該事務(wù)。如果當(dāng)前沒有事務(wù),則拋出異常。
  • Propagation.REQUIRES_NEW : 創(chuàng)建一個新的事務(wù)。如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。也就是說不管外部方法是否開啟事務(wù),Propagation.REQUIRES_NEW 修飾的內(nèi)部方法都會新開啟自己的事務(wù),且開啟的事務(wù)相互獨立,互不干擾。
  • Propagation.NOT_SUPPORTED : 以非事務(wù)方式運行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起(不用)。
  • Propagation.NEVER : 以非事務(wù)方式運行,如果當(dāng)前存在事務(wù), 則拋出異常。
  • Propagation.NESTED : 如果當(dāng)前存在事務(wù),則創(chuàng)建一個事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運行。如果當(dāng)前沒有事務(wù),則該取值等價于 PROPAGATION_REQUIRED。
public enum Propagation {
 REQUIRED(0),
 SUPPORTS(1),
 MANDATORY(2),
 REQUIRES_NEW(3),
 NOT_SUPPORTED(4),
 NEVER(5),
 NESTED(6);
 private final int value;
 private Propagation(int value) {
 this.value = value;
 }
 public int value() {
 return this.value;
 }
}

NESTED 和 REQUIRED 區(qū)別:

  • 整個事務(wù)如果全部執(zhí)行成功,二者的結(jié)果是一樣的。
  • 如果事務(wù)一部分執(zhí)行成功,REQUIRED加入事務(wù)會導(dǎo)致整個事務(wù)全部回滾。NESTED嵌套事務(wù)可以實現(xiàn)局部回滾,不會影響上一個方法中執(zhí)行的結(jié)果。

一個非常形象的比喻:

比如一對新人要結(jié)婚了, 關(guān)于是否需要房子:

  • 1. Propagation.REQUIRED : 需要有房子。 如果你有房,我們就一起住,如果你沒房,我們就一起買房。(如果當(dāng)前存在事務(wù),則加入該事務(wù)。如果當(dāng)前沒有事務(wù),則創(chuàng)建一個新的事務(wù))
  • 2. Propagation.SUPPORTS : 可以有房子。如果你有房, 那就一起住。如果沒房,那就租房。 (如果當(dāng)前存在事務(wù),則加入該事務(wù)。如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運行)
  • 3. Propagation.MANDATORY : 必須有房子。要求必須有房,如果沒房就不結(jié)婚。(如果當(dāng)前存在事務(wù), 則加?該事務(wù)。如果當(dāng)前沒有事務(wù),則拋出異常)
  • 4. Propagation.REQUIRES_NEW : 必須買新房。不管你有沒有房,必須要兩個人一起買房。即使有房也不住。(創(chuàng)建一個新的事務(wù). 如果當(dāng)前存在事務(wù), 則把當(dāng)前事務(wù)掛起)
  • 5. Propagation.NOT_SUPPORTED : 不需要房。不管你有沒有房, 我都不住,必須租房。(以非事務(wù)方式運行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起)
  • 6. Propagation.NEVER : 不能有房子。(以非事務(wù)方式運行,如果當(dāng)前存在事務(wù),則拋出異常)
  • 7. Propagation.NESTED : 如果你沒房,就一起買房。如果你有房,我們就以房子為根據(jù)地。做點生意。(如果如果當(dāng)前存在事務(wù),則創(chuàng)建一個事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運行。如果當(dāng)前沒有事務(wù),則該取值等價于 PROPAGATION_REQUIRED )

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Springquartz的配置方式詳解

    Springquartz的配置方式詳解

    本文介紹了在Spring框架中使用Quartz進(jìn)行任務(wù)調(diào)度的三種方式:使用@Scheduled注解、XML配置和Java配置,每種方式都有其特點和適用場景,感興趣的朋友一起看看吧
    2025-01-01
  • Java連接postgresql數(shù)據(jù)庫的示例代碼

    Java連接postgresql數(shù)據(jù)庫的示例代碼

    本篇文章主要介紹了Java連接postgresql數(shù)據(jù)庫的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • spring boot application properties配置實例代碼詳解

    spring boot application properties配置實例代碼詳解

    本文通過代碼給大家介紹了spring boot application properties配置方法,需要的的朋友參考下吧
    2017-07-07
  • Java的線程與進(jìn)程以及線程的四種創(chuàng)建方式

    Java的線程與進(jìn)程以及線程的四種創(chuàng)建方式

    這篇文章主要為大家詳細(xì)介紹了Java的線程與進(jìn)程以及線程的四種創(chuàng)建方式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • Java的JSON轉(zhuǎn)換類庫GSON的基礎(chǔ)使用教程

    Java的JSON轉(zhuǎn)換類庫GSON的基礎(chǔ)使用教程

    GSON是谷歌開源的一款Java對象與JSON對象互相轉(zhuǎn)換的類庫,Java的JSON轉(zhuǎn)換類庫GSON的基礎(chǔ)使用教程,需要的朋友可以參考下
    2016-06-06
  • java控制臺實現(xiàn)聊天程序

    java控制臺實現(xiàn)聊天程序

    這篇文章主要為大家詳細(xì)介紹了java控制臺實現(xiàn)聊天程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • SpringBoot事務(wù)使用及回滾實現(xiàn)代碼詳解

    SpringBoot事務(wù)使用及回滾實現(xiàn)代碼詳解

    這篇文章主要介紹了SpringBoot事務(wù)使用及回滾實現(xiàn)代碼詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08
  • springboot項目如何配置多數(shù)據(jù)源

    springboot項目如何配置多數(shù)據(jù)源

    本文介紹了如何在SpringBoot項目中配置多數(shù)據(jù)源,包括配置多個數(shù)據(jù)源、創(chuàng)建數(shù)據(jù)源配置類、配置事務(wù)管理器以及使用不同的Mapper,從而實現(xiàn)跨數(shù)據(jù)庫操作
    2025-03-03
  • Java面試Socket編程常用參數(shù)設(shè)置源碼問題分析

    Java面試Socket編程常用參數(shù)設(shè)置源碼問題分析

    這篇文章主要為大家介紹了Java編程中關(guān)于Socket結(jié)構(gòu)分析,常用參數(shù)設(shè)置源碼示例以及面試中的問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03
  • Spring注解之@Import的簡單介紹

    Spring注解之@Import的簡單介紹

    @Import是Spring基于Java注解配置的主要組成部分,下面這篇文章主要給大家介紹了關(guān)于Spring注解之@Import的簡單介紹,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12

最新評論