1. 程式人生 > >鏈式方法呼叫的事務問題剖析

鏈式方法呼叫的事務問題剖析

最近做了分散式的專案,當然沒有設計分散式事務的處理,一條邏輯線太長,方法調方法,所以之間的事務問題就暴露出來了 我已陣亡,直接碼程式碼吧  

@Service
public class TransactionalServiceImpl implements TransactionalService {

    @Autowired
    private CgpMngUserbraService cgpMngUserbraService;

    @Transactional
    @Override
    public void method() {
        List<CgpMngUserbra> cgpMngUserbras = cgpMngUserbraService.selectUserBraRules(0, 0);
        if (null == cgpMngUserbras || 0 == cgpMngUserbras.size()) {
            cgpMngUserbraService.insertUserBraRules(0, 0, "method");
        }
        method2();
    }

//    @Transactional//此處事務不會生效,原因可閱讀上一篇部落格
//    傳送門---> https://blog.csdn.net/fanxb92/article/details/81296005
    public void method2() {
        List<CgpMngUserbra> cgpMngUserbras = cgpMngUserbraService.selectUserBraRules(0, 0);
        if (null == cgpMngUserbras || 0 == cgpMngUserbras.size()) {
            cgpMngUserbraService.insertUserBraRules(0, 0, "method2");
        }
        TransactionalServiceImpl transactionalService = (TransactionalServiceImpl) AopContext.currentProxy();
        transactionalService.method3();
    }

    @Transactional
//    @Transactional(propagation = Propagation.REQUIRES_NEW)
//    @Transactional(propagation = Propagation.NESTED)
    public void method3() {
        List<CgpMngUserbra> cgpMngUserbras = cgpMngUserbraService.selectUserBraRules(0, 0);
        if (null == cgpMngUserbras || 0 == cgpMngUserbras.size()) {
            cgpMngUserbraService.insertUserBraRules(0, 0, "method3");
        }
    }
}

先介紹一下測試邏輯:method,method2,method3三個方法都會在一張表儲存同一條資料,並且鏈式呼叫。

method2加事務是不生效的,method2中事務和method中保持一致,參照程式碼中部落格連結。

method3上面三種事務處理方式 第一種@Transactional,method3中事務和前面保持一致(method方法上註解產生的事務中),全部執行完畢,資料庫中一條資料。 一定是全部執行完畢哦,中途打斷點,method中還為插入到資料庫,因為方法未結束,未commit。

第二種@Transactional(propagation = Propagation.REQUIRES_NEW),method3開啟了一個新的事務,會將已有的事務掛起, 同樣,方法全部執行完畢後資料庫兩條資料,資料庫記錄截圖如下:

可見,是method中資料入庫時間在前,分析===> !!!!!!!!!此處非常重要,可能說的不太簡潔精確,仔細體會!!!!!!!!!!!!!!!!!! method中執行insert,但未commit,未插入到資料庫 method3中執行insert,執行完畢commit,資料庫中會先插入記錄(在method3結束但method未結束的地方打斷點,會看到資料庫已經有記錄了), 同時method方法也結束,method事務commit,資料庫中插入記錄。(method3是新事務,同一事務會查詢快取,所以不在同一個事務中也沒有啦,查詢資料庫是沒有記錄的,也會入庫)。 開啟新事務,方法執行完畢就會提交,資料庫中有記錄,與前面事務不影響。但插入時間,看程式碼具體邏輯,在前的插入時間在前。 第三種@Transactional(propagation = Propagation.NESTED) 丟擲異常JpaDialect does not support savepoints - check your JPA provider's capabilities public JpaTransactionManager() {setNestedTransactionAllowed(true);}

後來才知道Hibernate也不支援Nested Transaction,測試不了,只能用jdbc事務了,使用JdbcTemplate。

好吧,就先聊這麼多吧。謝謝閱讀。