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

目錄

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

事務(wù)示例

示例一

示例二

示例三

示例四

示例五

示例六

事務(wù)原理?

@EnableTransactionManagement

執(zhí)行代理對象目標方法


事務(wù)示例 示例一

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

@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對外提供接口做測試

@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());
    }

}

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

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

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

示例二

在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é)果還是一樣,都會被回滾。因為test()方法是調(diào)用的TransactionService原始對象的abc()方法。

示例三

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

最終結(jié)果還是一樣都會回滾,因為這個線程只會創(chuàng)建一個事務(wù),同一個事務(wù)要么全部回滾,要么全部提交。

示例四

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

最終兩個方法執(zhí)行的數(shù)據(jù)庫更新操作還是會回滾,因為線程在執(zhí)行abc()方法后拋出的異常,在test()方法中并沒有處理這個異常,所以兩個事務(wù)都會回滾。

示例五

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

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

示例六

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

思考一會。。。

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

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

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

事務(wù)原理? @EnableTransactionManagement

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

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

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

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

執(zhí)行代理對象目標方法

a、當調(diào)用被代理對象目標方法時,會進入TransactionInterceptor#invoke()方法,執(zhí)行invokeWithinTransaction()方法

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

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

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

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

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

流程圖

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

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

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

廣告

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

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