方法加上@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