記一次 Spring Boot 中 @Transactional事務中使用內置鎖限制總數失效的BUG

前言:業務需要,最多隻能綁定5個,目前不考慮集羣,單體服務下的內容

第一版代碼:

@Transactional(rollbackFor = {CommonException.class}, propagation = Propagation.REQUIRED)
    public Object bindCommonUsedPatient(CommonUsedPatientRequest commonUsedPatientRequest, User user) throws CommonException, ParseException {

        synchronized (this){
            //查詢總綁定個數  超過則拋出異常
            //未超過 則向數據庫插入一條數據 佔位 使用了事務
        }

        //執行其它邏輯
    }

失效原因:同步代碼塊在事務中,一個事務插入了一條數據之後,在執行其它邏輯,並未完成事務時,另一個線程在另一個事務中無法看見之前插入的數據,導致統計數量失效

第二版代碼:

@Transactional(rollbackFor = {CommonException.class}, propagation = Propagation.REQUIRED)
    public Object bindCommonUsedPatient(CommonUsedPatientRequest commonUsedPatientRequest, User user) throws CommonException, ParseException {

        checkCommonUsedPatientAndInsert();
        //執行其它邏輯
    }

@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
   public synchronized CommonUsedPatient checkCommonUsedPatientAndInsert(CommonUsedPatientRequest commonUsedPatientRequest, User user) throws CommonException {
          //查詢總綁定個數  超過則拋出異常
          //未超過 則向數據庫插入一條數據 佔位 使用了事務
    }

改進方法:將插入數據庫的操作封裝爲方法,並指定事務的傳播行爲爲 REQUIRES_NEW

失效原因:加註解都是生成代理類,事務的功能都在代理類內部,實例方法A調用實例方法B是直接調用,不走代理類,所以事務未生效

第三版代碼:

將 checkCommonUsedPatientAndInsert 方法寫到另外的 類中,測試OK

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章