上一篇 <<<Spring AOP核心源码解读
下一篇 >>>Spring声明事务原理及核心源码分析
事务的分类
a、编程式事务控制【手动控制事务】
Jdbc代码:
Conn.setAutoCommite(false); // 设置手动控制事务
Hibernate代码:
Session.beginTransaction(); // 开启一个事务
优势:粒度更细,更灵活,可以指定方法甚至是里面的某几行
劣势:开发繁琐,每次都要开启、提交和回滚
b、声明式事务控制
分为XML版本和注解格式
原理:使用编程事务+反射机制进行包装,核心是基于AOP实现
优势:代码最大程度的解耦,移除配置或注释即可
劣势:只能对整个方法(aop只能拦截到方法)启用事务,不够灵活
管理类:
Jdbc技术:DataSourceTransactionManager
Hibernate技术:HibernateTransactionManager
Spring声明事务失效之谜(使用Spring事务的时候注意的地方)
在@Transactional注解的方法上如果把异常捕获了,导致拦截器的异常无法捕获,就无法执行回滚操作,事务自然就失效了。
可以在捕获的里面加上这句话手动回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
事务传播属性Propagation(行为)
PROPAGATION_REQUIRED【关键点:同一个事务】—如果当前有事务,就用当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
场景: 不同的类,class1,class2
class1.fun1--->class2.fun2: fun1调用fun2 ,无论在fun1还是fun2里发生unchecked异常[不论是否catch处理异常],都会触发整个方法的回滚.
PROPAGATION_REQUIRES_NEW【关键点:2个事务是单独的,没有依赖关系】--如果当前有事务,则挂起当前事务,然后新创建一个事务,如果当前没有事务,则自己创建一个事务。
场景: 日志记录
class1.fun1--->class2.fun2: fun1调用fun2 ,
如果fun2抛出异常且被catch处理,则fun2回滚,fun1不回滚.
如果fun2抛出异常且没被catch处理,则fun2,fun1都回滚.
如果fun1抛出异常,则fun1回滚,fun2不回滚.
PROPAGATION_NESTED【关键点:2个事务是依赖关系,fun2依赖fun1】--如果当前存在事务,则嵌套在当前事务中。如果当前没有事务,则新建一个事务自己执行(和required一样)。嵌套的事务使用保存点作为回滚点,当内部事务回滚时不会影响外部事物的提交;但是外部回滚会把内部事务一起回滚回去。(这个和新建一个事务的区别)
场景:
class1.fun1--->class2.fun2: fun1调用fun2,
如果fun2抛出异常且在fun1里catch处理了,则fun2回滚,fun1不回滚, 如果没有catch,则fun1也回滚.
如果fun1抛出异常,则fun1和fun2都回滚.
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。//如果外层方法没有事务,就会以非事务进行执行。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务就把当前事务挂起,执行完后恢复事务(忽略当前事务);
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_NEVER (never) :以非事务方式执行,如果当前存在事务,则抛出异常。(当前必须不能有事务)
推荐阅读:
<<<Spring IOC的初始化原理
<<<SpringBean的生命周期流程图
<<<SpringBean单例情况下解决循环依赖的原理
<<<Spring AOP的底层原理
<<<Spring AOP通知责任链模式图解
<<<Spring AOP核心源码解读
<<<Spring声明事务原理及核心源码分析
<<<手动事务和自定义注解事务代码参考
<<<Spring常用注解汇总
网友评论