spring用代理对象去调用方法才会生效, 在一个方法中去调用b其实是this去调用 ,所以不会生效
可以注入自己的service,用cglib代理的对象调用的b方法 ,可以让事务生效
然后spring三级缓存会帮我们过滤循环依赖的问题
1. 如果用了private就不会生效事务, 必须是public权限的方法
2.用final定义的方法不会生效事务,spring底层用了apo ,cglib或者jdk动态代理 生成了代理类,在代理类里面实现了事务功能
3.在a方法调用b方法(b方法使用了事务),在同一个类中的方法,直接调用会导致事务失效 (解决方法,建一个新的service,调用原service的a和b方法)
4.多线程里面调用也无法生效事务,spring事务是通过数据库连接实现的,当前线程中保存了一个map,ThreadLocal,同一个数据库连接才能回滚,<key
是数据源,value是数据库连接)
5.事物的传播特性,如果上下文存在事务,那么加入事务,如果不存在事务,会创建一个事务
6.自己捕获了异常,就不会回滚事务
场景
1. 事务方法不是public修饰的,将会导致事务失效
2. 事务方法使用了final或static修饰,将会导致事务失效
3. 方法内部之间调用,没有通过代理对象调用
4. 未被spring容器管理,方法不会产生事务
5. 多线程调用dao方法
6. 表不支持事务
7. 未开启事务
8. 使用了错误的事务传播行为
9. 自己吞了异常
10. 抛出了编译时异常
11. 自定义了指定异常类(rollbackFor属性)回滚,但实际发生的异常类与指定的异常类不一致
12. 事务回滚多了
细节(和上面每一条一一对应):
1. AbstractFallbackTransactionAttributeSource类中的computeTransactionAttribute方法中只规定了public修饰的方法才可以
2. spring事务底层使用了AOP,而AOP的底层是动态代理,动态代理分为两种:1,JDK自带的动态代理,需要被代理类实现接口,2,基于cglib的动态代理,需要继承被代理类,final修饰的方法不能被重写,所以会导致final修饰的方法事务失效
3. 方法拥有事务能力是因为使用了代理对象的方法
4. 没有使用@Service注解交给spring容器管理
5. 不同线程获取到的数据库连接不一样,从而是两个不同的事务,spring事务是通过数据库连接来实现的(ThreadLocal),同一个数据库连接才可以同时提交和同时回滚
6. 例如mysql的表使用了myisam引擎
7. 非springboot项目,例如传统spring项目,需要配置事务管理器开启事务
8. @Transactional注解的propagation为NEVER(方法不支持事务)
9. 使用了try、catch捕获了异常而没有抛出异常,事务不会回滚,spring会认为程序是正常的
10. spring事务默认支持运行时异常的回滚,如果开发人员自己捕获并在catch里抛出了编译时异常,则不会回滚
11. 自定义了指定异常(rollbackFor属性)回滚,但实际发生的异常与指定的异常不一致
12. 一个方法内有两个事务方法调用a(),b(),其中b方法出现了异常,导致b方法向上抛出异常,使得a方法也跟着回滚了导致a方法事务失效