Transactional失效场景

场景一:事务方法内部捕捉了异常,但是没有抛出异常,导致事务操作不会进行回滚。

示例代码如下:

@Transactional(rollbackFor = Exception.class)
public void function() {
    try {
        testMapper.insertOne();

        testMapper.insertTwo();
    }catch (Exception e){
        //如果此时有异常,而没有抛,事务失效,不会回滚
        e.printStackTrace();

		//正常抛出时,事务不失效,回滚
		throw e;
    }
}

场景二: 在类内部调用类内部@Transactional标注的方法。

这种情况下也会导致事务不开启,比如有一个类Test,它的一个方法A,A再调用本类的方法B,则外部调用方法A之后,方法B的事务是不会起作用的。
原因分析:由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。
既然事务管理是基于动态代理对象的代理逻辑实现的,那么如果在类内部调用类内部的事务方法,这个调用事务方法的过程并不是通过代理对象来调用的,而是直接通过this对象来调用方法,绕过的代理对象,肯定就是没有代理逻辑了。

public void deleteUser() throws MyException{
    deleteUser2();
}

@Transactional
public void deleteUser2() throws MyException{
    userMapper.deleteUserA();
    int i = 1 / 0;
    userMapper.deleteUserB();
}

解决方式:
把当前类自己注入一下调用即可。(或者第一个方法deleteUser加注解,1、如果A加了@Transaction注解,B上有没有@Transaction注解,事务都是有效的,则AB在同一个事务中。)

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
	//自己注入自己
    @Autowired
    UserService userService;

	public void deleteUser() throws MyException{
	    userService.deleteUser2();
	}

	@Transactional
	public void deleteUser2() throws MyException{
	    userMapper.deleteUserA();
	    int i = 1 / 0;
	    userMapper.deleteUserB();
	}
}

场景三: 抛出非运行异常RuntimeException,且没有指定rollbackFor=异常类型

@Transactional
public void deleteUser() throws MyException{
    userMapper.deleteUserA();
    try {
        int i = 1 / 0;
        userMapper.deleteUserB();
    } catch (Exception e) {
        throw new MyException();
    }
}

解决方式:
如果指定了回滚异常类型为Exception,那么就可以回滚非RuntimeException类型异常了。

@Transactional(rollbackFor = Exception.class)

总结一下
@Transactional只能回滚RuntimeException和RuntimeException下面的子类抛出的异常 不能回滚Exception异常
如果需要支持回滚Exception异常请用@Transactional(rollbackFor = Exception.class)
这里如果是增删改的时候我建议大家都使用@Transactional(rollbackFor = Exception.class)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值