当前添加事务的方法内可能出现异常,但是需要去捕获这个异常,然后返回指定格式的数据。同时将当前方法内的所有改库操作都回滚。
解决思路:
可能出现异常就将相关代码用try catch 捕获,但是捕获异常后事务就不会生效;所以希望在捕获异常后,手动去回滚事务,然后再组装指定的数据个数返回;
上代码:
@Transactional(rollbackFor = Exception.class)
@Override
/**
* 测试事务回滚(手动回滚)
*/
public Map<String,Object> updateAA(Long id) {
Map<String,Object> resMap = new HashMap<>();
try {
//修改 A 表数据【直接调用注入的 dao 层的修改方法】
aaMapper.updAA(id);
//修改 B 表数据【调用 当前类 中的修改操作方法】
updateBB(id);
//修改 B 表数据【调用 其它类 中的修改操作方法】
//test.updateBB(id);
log.info("两张表都已修改成功!");
//模拟异常
int i = 1/0;
} catch (Exception e) {
log.info("出现异常"+e);
//手动回滚事务**
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//组装异常情况下需要返回的数据
resMap.put("code","500");
resMap.put("msg","出现了异常");
return resMap;
}
//组装正常常情况下需要返回的数据
resMap.put("code","200");
resMap.put("msg","操作成功");
return resMap;
}
测试点:
1,是否可以回滚当前类中未加@Transactional 注解的修改方法;【是】
2,是否可以回滚注入的其他类中中未加@Transactional 注解的修改方法;【是】
3,…待补充
>>使用 @Transactional 注解事务失效的场景:
1,注解用在了被 final、static 修饰的方法或者类上;
2,注解用在了非public 修饰的方法上;
3,当前类没有被Spring 管理;
4,多线程场调用;
5,数据库不支持事务;
6,异常被捕获;(*本示例中需要解决的问题)
>>事务的传播机制;
1,如果当前不存在事务,子方法就自己开启事务。父方法如果有事务,它就跟随父方法的事务被包裹其中。总之 REQUIRED 就是必须运行在事务中【为缺省值默认传播机制】
@Transactional(propagation = Propagation.REQUIRED)
2,如果当前存在了事务,它就也被包裹运行在这个事务中。如果父方法没有开启事务,它就以无事务运行
@Transactional(propagation = Propagation.SUPPORTS)
3,要求当前必须存在事务,否则这个子方法就抛出异常 IllegalTransactionStateException
@Transactional(propagation = Propagation.MANDATORY)
4,不管当前有没有事务,都不在那个事务中运行,自己一定会单独开启一个独立的事务运行
@Transactional(propagation = Propagation.REQUIRES_NEW)
5,如果当前已经存在了事务,则会挂起这个事务。子方法它坚决不在事务中运行
@Transactional(propagation = Propagation.NOT_SUPPORTED)
6,和 Propagation.MANDATORY 相反,子方法要求当前不能存在事务。否则它就抛出异常 IllegalTransactionStateException
和 Propagation.MANDATORY 相反,子方法要求当前不能存在事务。否则它就抛出异常 IllegalTransactionStateException
7,如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与 PROPAGATION_REQUIRED 类似的操作
@Transactional(propagation = Propagation.NESTED)