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