@Transactional 手動數據回滾 No transaction aspect-managed TransactionStatus in scope ; Transaction rolled back because it has been marked as rollback-only


方法加上@Transactional 注解,手動數據回滾

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

 

遇到的兩個問題:

1.  org.springframework.transaction.NoTransactionException: No transaction aspect-managed TransactionStatus in scope

 

2.  org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

 

 

我的最終代碼如下,解決了以上的兩個問題:

    @RequestMapping(value="/insert",produces = "application/json;charset=utf-8", method = RequestMethod.POST)
    @Transactional(propagation = Propagation.NESTED)
    public String insert(@RequestBody SysUser user, HttpServletRequest request, HttpServletResponse response){

        //獲取當前登錄系統的用戶信息
        SysUser currentUser = getUser();
        user.setCreateTime(new Date()); //設置注冊時間
        user.setPassword(MD5Tools.generate(user.getPassword()));// 密碼MD5轉碼
        ReturnData returnData = sysUserService.addUser(currentUser, user);

        return returnData.toString();
    }

 

   @Override
    @Transactional(propagation = Propagation.NESTED)
    public ReturnData addUser(SysUser currentUser, SysUser user) {
/*
         * 根據用戶名和站點id查詢用戶是否已經存在
         * */
//        SysUser u = sysUserMapper.selectByLoginNameAndSiteId(user.getLoginName(),user.getSiteId());
        SysUser u = sysUserMapper.selectByLoginNameAndSiteId(user.getLoginName(), null);
        if (u != null)
            return ReturnData.FAIL("用戶名已存在");

        //1.添加用戶
        int res1 = sysUserMapper.insertSelective(user);
        if (res1 == 0)
            return ReturnData.FAIL("添加失敗");

        //2.分配用戶角色
        int res2 = userRoleService.insertByUidAndRoleIdList(user.getId(), user.getRoleIds());
        if (res2 == 0) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); return ReturnData.FAIL("用戶角色分配失敗,數據回滾");
        }

        //3.分配用戶可管理的站點
        int res3 = sysUserSiteService.insertByUidAndSiteIdList(user.getId(), user.getSiteIds());

        //4.設置用戶的默認登錄站點
        int res4 = sysUserSiteService.setUserDefaultLoginSite(user.getId(), user.getDefaultSiteId());
        if (res3 == 0 | res4 == 0) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); return ReturnData.FAIL("用戶管理站點分配失敗,數據回滾");
        }

        return ReturnData.SUCCESS("添加成功");
    }

 

問題分析及解決方法:

出現以上問題一:是因為我在方法 addUser() 上加了注解@Transactional,而方法insert()上沒有使用注解@Transactional導致。兩個方法都加上注解即可解決

問題一解決后,當在addUser()執行數據回滾操作時,即人為數據回滾 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly() 時,問題二

出現了。網上搜了好多都說加上try catch 捕獲異常,然而任我在哪加都不行,因為問題二的異常是在insert()方法執行結果后才拋出的一個異常,try catch沒辦法

捕獲。解決方法是改變兩個方法的事務傳播機制,即注解改為 @Transactional(propagation = Propagation.NESTED)。

出現問題二是因為我之前兩個方法都使用注解 @Transactional,默認的事務傳播機制為 Propagation.REQUIRED。

Spring事務傳播機制匯總如下:

Propagation.REQUIRED:如果當前沒有事務,就新建一個事務,如果已經存在一個事務,就加入到這個事務中。默認策略
Propagation.SUPPORTS:支持當前事務,如果當前沒有事務,就以非事務方式執行。
Propagation.MANDATORY:使用當前的事務,如果當前沒有事務,就拋出異常。
Propagation.REQUIRES_NEW:新建事務,如果當前存在事務,把當前事務掛起。
Propagation.NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
Propagation.NEVER:以非事務方式執行,如果當前存在事務,則拋出異常。
Propagation.NESTED:如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與Propagation.REQUIRED類似的操作。

 

可參考:https://blog.csdn.net/qq_30336433/article/details/83111675

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM