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

詳解Spring事務(wù)和事務(wù)傳播機(jī)制

 更新時(shí)間:2024年12月02日 08:37:54   作者:2的n次方_  
本文主要介紹了MySQL中的事務(wù)以及如何在Spring框架中實(shí)現(xiàn)事務(wù)管理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1. 事務(wù)的回顧

在 MySQL 學(xué)習(xí)階段,已經(jīng)了解到了事務(wù)是一組操作的集合,也就是把所有的操作作為一個(gè)整體,一起向數(shù)據(jù)庫(kù)提交或者撤銷操作,要么同時(shí)成功,要么同時(shí)失敗

一個(gè)事務(wù)的操作流程包括了,開(kāi)啟事務(wù),執(zhí)行事務(wù)操作,提交事務(wù)或回滾事務(wù),對(duì)于回滾事務(wù)來(lái)說(shuō),如果程序在執(zhí)行過(guò)程中出現(xiàn)了錯(cuò)誤,那么此時(shí)就需要執(zhí)行回滾事務(wù)

2. 事務(wù)的實(shí)現(xiàn)方式

2.1. 編程式事務(wù)

Spring 手動(dòng)操作事務(wù)和 MySQL 操作事務(wù)類似,也是分為開(kāi)啟事務(wù),提交事務(wù),回滾事務(wù)等三個(gè)操作,需要用到 DataSourceTransactionManager (事務(wù)管理器)來(lái)進(jìn)行上述事務(wù)的操作,還需要用到 TransactionDefinition(事務(wù)的屬性,獲取事務(wù)時(shí)需要把這個(gè)類的對(duì)象傳進(jìn)去)

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;

    @Autowired
    private TransactionDefinition transactionDefinition;

    @RequestMapping("/registy")
    public String registy(String name, String password) {
        //開(kāi)啟事務(wù),獲取一個(gè)狀態(tài),之后回滾就回滾到了這個(gè)狀態(tài)
        TransactionStatus transaction = dataSourceTransactionManager.getTransaction(transactionDefinition);
        Integer reuslt = userService.insert(name, password);
        //提交事務(wù)(提交的是之前獲取的狀態(tài))
        dataSourceTransactionManager.commit(transaction);
        return "注冊(cè)成功";
    }
}

測(cè)試之后數(shù)據(jù)也是正常更新了

回滾的話調(diào)用的是 rollback 方法,再次進(jìn)行插入數(shù)據(jù),數(shù)據(jù)就沒(méi)有更新,不過(guò)自增 id 還是變成了 3,對(duì)比提交事務(wù)的日志可以看出,這次沒(méi)有提交事務(wù)的信息了

2.2. 聲明式事務(wù)

上面的方式是比較麻煩的,需要自己寫(xiě)一大堆信息,來(lái)看聲明式事務(wù)是如何操作的

首先需要添加依賴:

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

只需在要執(zhí)行的方法上添加@Transactional注解,添加之后,如果沒(méi)有發(fā)生異常就正常執(zhí)行,如果發(fā)生了異常就回滾事務(wù)

來(lái)看異常的情況:

這時(shí)事務(wù)就沒(méi)有提交,進(jìn)行了回滾

3. @Transactional

@Transactional 可以用來(lái)修飾方法或類,修飾方法時(shí),只有修飾 public 方法時(shí)才生效,修飾其他方法時(shí)不會(huì)報(bào)錯(cuò),但也不生效,修飾類時(shí),對(duì)該類中所有的 public 方法都生效

在目標(biāo)方法執(zhí)行開(kāi)始之前會(huì)自動(dòng)開(kāi)啟事務(wù),執(zhí)行結(jié)束之后會(huì)自動(dòng)提交事務(wù),如果方法執(zhí)行過(guò)程中出現(xiàn)異常且異常未被捕獲,就進(jìn)行事務(wù)回滾操作

例如,把上面的異常代碼 catch 起來(lái),事務(wù)就正常提交了

但是如果捕獲之后又進(jìn)行拋出,那么事務(wù)還是會(huì)回滾的

還可以通過(guò)調(diào)用 setRollbackOnly 方法進(jìn)行手動(dòng)回滾

這樣的話把異常捕獲之后還可以回滾事務(wù)

3.1. rollbackFor

@Transactional默認(rèn)只在遇到 RuntimeException 和 Error 時(shí)才進(jìn)行回滾,非運(yùn)行時(shí)異常就不會(huì)滾,來(lái)演示一下發(fā)生非運(yùn)行異常時(shí)的情況:

雖然此時(shí)拋出了異常,但是事務(wù)還是提交了,并沒(méi)有進(jìn)行回滾,可以通過(guò)設(shè)置@Transactional注解的 rollbackFor 屬性來(lái)指定那些異常要回滾

把 rollbackFor 設(shè)置為 Exception.class,表示 Exception 底下的子類異常都會(huì)發(fā)生回滾

@Transactional(rollbackFor = Exception.class)
@RequestMapping("/r3")
public String r3(String name, String password) throws IOException {
    Integer reuslt = userService.insert(name, password);
    if (true) {
        throw new IOException();
    }
    return "注冊(cè)成功";
}

此時(shí)再次測(cè)試,事務(wù)就回滾了

3.2. isolation

@Transactional 注解的 isolation 屬性是可以設(shè)置事務(wù)的隔離級(jí)別的,參數(shù)類型是一個(gè) Isolation 的枚舉類,依次表示當(dāng)前數(shù)據(jù)庫(kù)默認(rèn)使用的隔離級(jí)別和事務(wù)的四種隔離級(jí)別

可以根據(jù)需要進(jìn)行設(shè)置

//設(shè)置事務(wù)的隔離級(jí)別
@Transactional(isolation = Isolation.DEFAULT)
@RequestMapping("/r4")
public String r4(String name, String password) throws IOException {
    Integer reuslt = userService.insert(name, password);
    if (true) {
        throw new IOException();
    }
    return "注冊(cè)成功";
}

4. 事務(wù)傳播機(jī)制

事務(wù)傳播機(jī)制是指在多個(gè)事務(wù)方法相互調(diào)用時(shí),定義事務(wù)如何在這些方法之間傳播的規(guī)則,也就是延用調(diào)用方法的事務(wù)還是再重新開(kāi)啟一個(gè)新事務(wù)

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

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

描述

理解(有 A,B 兩個(gè)方法,A 調(diào)用 B 對(duì)于 B 來(lái)說(shuō))

Propagation.REQUIRED

默認(rèn)的事務(wù)傳播級(jí)別。如果當(dāng)前存在事務(wù),則加入該事務(wù)。如果當(dāng)前沒(méi)有事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。

A 有事務(wù)就用 A 的,沒(méi)有 B 就再開(kāi)啟新的

Propagation.SUPPORTS

如果當(dāng)前存在事務(wù),則加入該事務(wù)。如果當(dāng)前沒(méi)有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。

A 沒(méi)有事務(wù)就算了,B 就按照沒(méi)有事務(wù)的方式執(zhí)行

Propagation.MANDATORY

如果當(dāng)前存在事務(wù),則加入該事務(wù)。如果當(dāng)前沒(méi)有事務(wù),則拋出異常。

如果 A 沒(méi)有事務(wù),就拋出異常

Propagation.REQUIRES_NEW

如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。也就是說(shuō)不管外部方法是否開(kāi)啟事務(wù),Propagation.REQUIRES_NEW 修飾的內(nèi)部方法都會(huì)新開(kāi)啟自己的事務(wù),且開(kāi)啟的事務(wù)相互獨(dú)立,互不干擾。

不管 A 有沒(méi)有事務(wù),B 都要開(kāi)啟新事務(wù)

Propagation.NOT_SUPPORTED

以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起(不用)。

不管 A 有沒(méi)有事務(wù),B 都以非事務(wù)方式執(zhí)行

Propagation.NEVER

以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常。

B 以非事務(wù)方式執(zhí)行,如果 A 有事務(wù)就拋出異常

Propagation.NESTED

如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來(lái)運(yùn)行。如果當(dāng)前沒(méi)有事務(wù),則該取值等價(jià)于 PROPAGATION_REQUIRED。

如果 A 有事務(wù),B 就創(chuàng)建一個(gè)嵌套事務(wù),如果沒(méi)有就創(chuàng)建新的

4.1. REQUIRED

把 UserService 和 LogService 的兩個(gè)方法都設(shè)置為 REQUIRED

@Slf4j
@RestController
@RequestMapping("/propaga")
public class PropagationController {
    @Autowired
    private UserService userService;
    @Autowired
    private LogService logService;

    @Transactional
    @RequestMapping("/r1")
    public String registy(String name, String password) {
        userService.insert(name, password);
        logService.insertLog(name,"用戶注冊(cè)");
        return "注冊(cè)成功";
    }
}

在 PropagationController 中進(jìn)行調(diào)用,此時(shí) registy 就相當(dāng)于 A ,調(diào)用的兩個(gè)方法相當(dāng)于 B,運(yùn)行之后,如果其中一個(gè)方法發(fā)生異常,那么 registy 方法的整個(gè)事務(wù)都會(huì)回滾,也就是他們都用的是 A 的事務(wù)

4.2. REQUIRES_NEW

把 UserService 和 LogService 的兩個(gè)方法都設(shè)置為 REQUIRES_NEW

此時(shí)就是無(wú)論 A 有沒(méi)有事務(wù), B 都新創(chuàng)建事務(wù),所以當(dāng) B 的一個(gè)方法有異常時(shí),是不會(huì)影響其他方法的

4.3. NEVER

如果設(shè)置為 NEVER 的話,A 調(diào)用 B,A 如果存在事務(wù),就會(huì)報(bào)錯(cuò)

把 A 的事務(wù)取消掉就不會(huì)報(bào)錯(cuò)了

4.4. NESTED

NESTED 是如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來(lái)運(yùn)行,所以說(shuō) A 和 B 不是同一個(gè)事務(wù),那么當(dāng) B 的一個(gè)方法出現(xiàn)異常時(shí)進(jìn)行回滾,另一個(gè) A 調(diào)用的方法是不受影響的,也印證了這兩個(gè)不是同一個(gè)事務(wù),確實(shí)是創(chuàng)建了一個(gè)嵌套事務(wù)

和 REQUIRED 不同的是,那里用的是同一個(gè)事務(wù),其中一個(gè)回滾,都要回滾,這里可以只是自己的事務(wù)進(jìn)行回滾,也就是實(shí)現(xiàn)局部回滾

到此這篇關(guān)于詳解Spring事務(wù)和事務(wù)傳播機(jī)制的文章就介紹到這了,更多相關(guān)Spring 事務(wù)和事務(wù)傳播機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java實(shí)現(xiàn)給出分?jǐn)?shù)數(shù)組得到對(duì)應(yīng)名次數(shù)組的方法

    java實(shí)現(xiàn)給出分?jǐn)?shù)數(shù)組得到對(duì)應(yīng)名次數(shù)組的方法

    這篇文章主要介紹了java實(shí)現(xiàn)給出分?jǐn)?shù)數(shù)組得到對(duì)應(yīng)名次數(shù)組的方法,涉及java針對(duì)數(shù)組的遍歷、排序及運(yùn)算的相關(guān)技巧,需要的朋友可以參考下
    2015-07-07
  • spring boot2.0總結(jié)介紹

    spring boot2.0總結(jié)介紹

    今天小編就為大家分享一篇關(guān)于spring boot2.0總結(jié)介紹,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • Java利用棧實(shí)現(xiàn)簡(jiǎn)易計(jì)算器功能

    Java利用棧實(shí)現(xiàn)簡(jiǎn)易計(jì)算器功能

    這篇文章主要為大家詳細(xì)介紹了Java利用棧實(shí)現(xiàn)簡(jiǎn)易計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Java線程中的ThreadLocal詳細(xì)分析

    Java線程中的ThreadLocal詳細(xì)分析

    這篇文章主要介紹了Java線程中的ThreadLocal詳細(xì)分析,ThreadLocal?提供線程的局部變量,每個(gè)線程都可以通過(guò)?get()和?set()對(duì)局部變量進(jìn)行操作而不會(huì)對(duì)其他線程的局部變量產(chǎn)生影響,實(shí)現(xiàn)了線程之間的數(shù)據(jù)隔離,需要的朋友可以參考下
    2023-09-09
  • MyBatis-Plus3.x版本使用入門和踩過(guò)的坑

    MyBatis-Plus3.x版本使用入門和踩過(guò)的坑

    Mybatis-Plus是Mybatis的增強(qiáng)版,他只是在Mybatis的基礎(chǔ)上增加了功能,且并未對(duì)原有功能進(jìn)行任何的改動(dòng),本文給大家說(shuō)一下MyBatis-Plus3.x版本使用入門和踩過(guò)的坑,感興趣的朋友跟隨小編一起看看吧
    2023-10-10
  • IDEA2019.2.2配置Maven3.6.2打開(kāi)出現(xiàn)Unable to import Maven project

    IDEA2019.2.2配置Maven3.6.2打開(kāi)出現(xiàn)Unable to import Maven project

    這篇文章主要介紹了IDEA2019.2.2配置Maven3.6.2打開(kāi)出現(xiàn)Unable to import Maven project,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java 使用反射調(diào)用jar包中的類方式

    Java 使用反射調(diào)用jar包中的類方式

    這篇文章主要介紹了Java 使用反射調(diào)用jar包中的類方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • IDEA2020.1啟動(dòng)SpringBoot項(xiàng)目出現(xiàn)java程序包:xxx不存在

    IDEA2020.1啟動(dòng)SpringBoot項(xiàng)目出現(xiàn)java程序包:xxx不存在

    這篇文章主要介紹了IDEA2020.1啟動(dòng)SpringBoot項(xiàng)目出現(xiàn)java程序包:xxx不存在,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • IDEA斷點(diǎn)調(diào)試,斷點(diǎn)不起作用的解決

    IDEA斷點(diǎn)調(diào)試,斷點(diǎn)不起作用的解決

    這篇文章主要介紹了IDEA斷點(diǎn)調(diào)試,斷點(diǎn)不起作用的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java函數(shù)式編程(七):MapReduce

    Java函數(shù)式編程(七):MapReduce

    這篇文章主要介紹了Java函數(shù)式編程(七):MapReduce,本文是系列文章的第7篇,其它文章請(qǐng)參閱本文底部的相關(guān)文章,需要的朋友可以參考下
    2014-09-09

最新評(píng)論