1.Spring只会对RuntimeException和Err的子类进行检查
原因:像检查异常它是不会回滚的.如:FileNotFoundException
解决办法:配置参数rollbackFor=异常类.class 指定检查异常 或者改成顶级Exception.class
2.业务内方法自己进行try-catch包住,导致不能正常回滚
原因:事务通知只有自己捕捉到了异常才能进行回滚处理,如果是自己处理的,就不会进行回滚.(相当于,事务的异常在最底层,如果外面的异常捕捉了,导致异常无法到最底层,所以底层不知道出现了异常)
解决办法:1.自己在catch块里面手动把异常抛出去,2.使用事务异常通知,也是在catch语句块里面加=>TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
3.aop切面的顺序导致事务不能正确回滚
原因:事务的优先级最低,但是如果自定义的切面的优先级和他一样,则还是自定义切面在内层,这时如果抛出异常,被自定义的切面捕获了, 事务就没有收到异常通知,
解决办法:1.自己在catch块里面手动把异常抛出去,2.使用事务异常通知,也是在catch语句块里面加=>TransactionInterceptor.currentTransactionStatus().setRollbackOnly();(同2一致)
4.@Transactional 必须加在public方法上
原因:Spring默认@Transactional必须加在public方法上
5.父子容器导致事务失效
原因:在传统的ssm整合的时候会有两个容器,就会产生,有两个相同service
解决办法:不要用父子容器,springboot没有这个父子容器
6.调用本类方法导致传播行为失效,使用this或者直接调
原因:本类方法调用不经过代理,因此无法增强
解决办法:1.使用AopContext.currentProxy(),好像要配置什么东西.拿到代理对象.2.改变调用方式
7.@Transactional没有保证原子行为
在多线程情况下:你查询的时候,余额是够的,但是下面做了修改,修改过后并没有提交,,就是因为select不会让其他线程阻塞.
原因:事务的原子性仅包含insert.update.delete.select...forupdate语句,select方法并不会导致其他线程阻塞
解决办法:在你的select语句后面加上for update,它就不会查询当前正在执行的事务了
8.@Transactional方法导致的synchronized失效
原因:synchronized保证的仅是目标方法的原子性,环绕目标方法的还有commit操作,它们斌没有在sync块中=>synchronized方法只包含了方法本身,但是commit行为,并不在方法体内,所以会失效.
解决办法:1.扩大synchronized范围=>扩到到调用方,谁调用就把谁扩起来.2.select语句后面加上for update