spring事物使用示例及原理總結(jié)-創(chuàng)新互聯(lián)

目錄

渝水網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),渝水網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為渝水成百上千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站制作要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的渝水做網(wǎng)站的公司定做!

事務(wù)示例

示例一

示例二

示例三

示例四

示例五

示例六

事務(wù)原理?

@EnableTransactionManagement

執(zhí)行代理對(duì)象目標(biāo)方法


事務(wù)示例 示例一

在test()方法直接調(diào)用abc()方法,并在test()方法添加@Transactional,test()和abc()方法分別會(huì)更新id=1和id=2的數(shù)據(jù)name字段,abc()方法中會(huì)拋出異常。

@Component
public class TransactionService {

    @Autowired
    private TransactionService service;

    @Resource
    private UserMapper userMapper;

    @Transactional(rollbackFor = Exception.class)
    public String test(String name, String target) throws Exception {
        User user = new User();
        user.setId(1l);
        user.setName(name);
        userMapper.updateById(user);
        abc(target);
        return "ok";
    }
    
    public void abc(String target) throws Exception {
        User user = new User();
        user.setId(2l);
        user.setName(target);
        userMapper.updateById(user);
        throw new Exception("error");
    }
    
}

使用TransactionController對(duì)外提供接口做測(cè)試

@RestController
public class TransactionController {

    @Autowired
    private TransactionService service;

    @GetMapping("testT")
    public String test(@RequestBody Mapmap) throws Exception {
        return service.test(map.get("name").toString(), map.get("target").toString());
    }

}

測(cè)試之前先看數(shù)據(jù)庫(kù)的值:

執(zhí)行??http://localhost:8080/testT?測(cè)試

不難看出,兩條更新操作都會(huì)被回滾。

示例二

在abc()方法中添加@Transactional(rollbackFor = Exception.class)注解

@Transactional(rollbackFor = Exception.class)
    public void abc(String target) throws Exception {
        User user = new User();
        user.setId(2l);
        user.setName(target);
        userMapper.updateById(user);
        throw new Exception("error");
    }

結(jié)果還是一樣,都會(huì)被回滾。因?yàn)閠est()方法是調(diào)用的TransactionService原始對(duì)象的abc()方法。

示例三

在TransactionService中新增TransactionService 類型的成員屬性,通過(guò)@Autowired注入spring bean對(duì)象,并在test()方法中使用service屬性調(diào)用abc(),其用意是調(diào)用spring創(chuàng)建的代理對(duì)象的abc()方法。

最終結(jié)果還是一樣都會(huì)回滾,因?yàn)檫@個(gè)線程只會(huì)創(chuàng)建一個(gè)事務(wù),同一個(gè)事務(wù)要么全部回滾,要么全部提交。

示例四

在abc()方法的注解改為@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW),其用意是同一個(gè)線程在執(zhí)行test()方法時(shí)創(chuàng)建一個(gè)事務(wù),在調(diào)用service.abc()方法時(shí)又會(huì)創(chuàng)建一個(gè)事務(wù)。

最終兩個(gè)方法執(zhí)行的數(shù)據(jù)庫(kù)更新操作還是會(huì)回滾,因?yàn)榫€程在執(zhí)行abc()方法后拋出的異常,在test()方法中并沒(méi)有處理這個(gè)異常,所以兩個(gè)事務(wù)都會(huì)回滾。

示例五

在test()方法中將service.abc()方法用try catch捕獲異常。

再次執(zhí)行,就會(huì)發(fā)現(xiàn)test()方法事務(wù)會(huì)提交,而abc()方法事務(wù)會(huì)回滾。如圖,id=1的name屬性修改james,id=2的name屬性沒(méi)有發(fā)生變化。

示例六

在test()方法中將service.abc()方法try catch捕獲,并且abc()方法使用的事務(wù)和test()方法使用同一個(gè)事務(wù),此時(shí)事務(wù)會(huì)提交還是回滾呢?還會(huì)出現(xiàn)和示例五中abc()方法更新操作回滾,test()方法更新操作提交的效果呢?

思考一會(huì)。。。

首先這兩個(gè)方法使用的是同一個(gè)事務(wù),故它們要么全部提交,要么全部回滾。那到底是回滾還是提交,將由跟spring事務(wù)管理器中的一個(gè)屬性相關(guān),該屬性為globalRollbackOnParticipationFailure,它默認(rèn)等于true,表示如果參與的事務(wù)有失敗的,則標(biāo)記為為回滾。如果將他設(shè)置為false,表示局部執(zhí)行失敗的事務(wù),也會(huì)標(biāo)記為提交。所以這個(gè)事務(wù)還是會(huì)回滾。

如果將事務(wù)管理器的globalRollbackOnParticipationFailure設(shè)置為false,那么該事務(wù)就會(huì)提交。

小結(jié):在a()方法調(diào)用b()方法時(shí),如果他們使用同一個(gè)事務(wù),他們的數(shù)據(jù)庫(kù)更新操作要么全部提交,要么全部回滾;如果b()方法事務(wù)傳播屬性為REQUIRES_NEW,表示在執(zhí)行b()方法時(shí)創(chuàng)建新事物,此時(shí)a()方法事務(wù)的提交和回滾可以不受b()方法的事務(wù)控制。?

事務(wù)原理? @EnableTransactionManagement

spring boot啟動(dòng)添加@EnableTransactionManagement注解,表示開(kāi)啟事務(wù)功能。spring解析@EnableTransactionManagement注解流程如下圖。

a、導(dǎo)入TransactionManagementConfigurationSelector類,執(zhí)行selectImports()方法,加載AutoProxyRegistrar和ProxyTransactionManagementConfiguration類。

b、spring在解析AutoProxyRegistrar時(shí)執(zhí)行registerBeanDefinitions()方法,它會(huì)將InfrastructureAdvisorAutoProxyCreator注冊(cè)到spring容器中,InfrastructureAdvisorAutoProxyCreator是一個(gè)BeanPostProccessor,在其父類中實(shí)現(xiàn)了postProcessBeforeInstantiation()方法,在實(shí)例化前會(huì)給目標(biāo)對(duì)象創(chuàng)建代理對(duì)象。

c、spring在解析ProxyTransactionManagementConfiguration時(shí)分別會(huì)創(chuàng)建3個(gè)bean對(duì)象,BeanFactoryTransactionAttributeSourceAdvisor、TransactionInterceptor和AnnotationTransactionAttributeSource,分別是advisor、advice和pointcut,advice是代理邏輯,pointcut是切入點(diǎn),advisor可以理解為是advice+pointcut組成的。

執(zhí)行代理對(duì)象目標(biāo)方法

a、當(dāng)調(diào)用被代理對(duì)象目標(biāo)方法時(shí),會(huì)進(jìn)入TransactionInterceptor#invoke()方法,執(zhí)行invokeWithinTransaction()方法

b、getTransaction()中創(chuàng)建事務(wù)對(duì)象,如果事務(wù)傳播屬性為REQUIRED,REQUIRES_NEW,NESTED時(shí),執(zhí)行startTransaction()開(kāi)啟并設(shè)置事務(wù)屬性。

c、首先從事務(wù)對(duì)象中獲取連接對(duì)象,將連接對(duì)象設(shè)置為不自動(dòng)提交。

d、執(zhí)行prepareTransactionInfo()方法創(chuàng)建TransactionInfo對(duì)象,并將getTransaction()返回的TransactionStatus對(duì)象設(shè)置到TransactionInfo對(duì)象,然后調(diào)用bindToThread()方法獲取當(dāng)前線程ThreadLocal對(duì)象中的TransactionInfo對(duì)象,將其賦值給oldTransactionInfo緩存起來(lái),將新創(chuàng)建的TransactionInfo對(duì)象設(shè)置到ThreadLocal對(duì)象中去。

d、執(zhí)行目標(biāo)方法

f、提交或者回滾,如果目標(biāo)方法執(zhí)行失敗,拋出異常,則會(huì)執(zhí)行completeTransactionAfterThrowing()進(jìn)行回滾,回滾之后執(zhí)行finally塊的cleanupTransactionInfo()方法,將緩存在oldTransactionInfo屬性的TransactionInfo對(duì)象重新設(shè)置到當(dāng)前線程的ThreadLocal對(duì)象中去;如果目標(biāo)方法執(zhí)行成功,則先執(zhí)行cleanupTransactionInfo()方法,再執(zhí)行commitTransactionAfterReturning()方法提交事務(wù)。

流程圖

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

新聞名稱:spring事物使用示例及原理總結(jié)-創(chuàng)新互聯(lián)
地址分享:http://bm7419.com/article18/dsshdp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、關(guān)鍵詞優(yōu)化、全網(wǎng)營(yíng)銷推廣、建站公司網(wǎng)站收錄、網(wǎng)站設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)