前言
上一篇文章主要讲解了mysql中一些事务的基本知识,但是我们在工作中基本是不会直接操作mysql的事务的,而是通过spring框架来处理的。这一篇就来研究下spring中的事务。
知识点
spring对于事务的支持 事务的传播机制
面试引导
spring执行某个操作,前9次成功,第10次失败。以下分别对应什么传播机制? A:全部回滚 B:前9次提交,第10次回滚
1.Spring对于事务的支持
1.1.声明式事务
即我们最常使用的@Transactional注解。
使用@Transactional
注解时一般要标注上如下两个参数
rollbackFor: 指定异常回滚。一般是 RuntimeExceptionpropagation: 事务的隔离级别这个我们一般采用了默认的 PROPAGATION_REQUIRED
1.2编程式事务
现在一般没人用了,通过
TransactionTemplate
来实现,此处不再赘述
2.事务的传播机制
我们在数据库中使用事务的时候,是通过事务开始-->业务逻辑-->事务结束
这样的流程进行的,是针对不同的单个事务。
而在Java业务代码中,通常是在一个方法上进行的事务操作,通过@Transactional
来实现,因此就涉及到了同一个事务操作涉及到多个方法的调用,
并且多个方法有可能不在一个事务中,那么这多个方法是分别提交各自的事务,还是需要合并到外层的事务一起提交,这就是我们事务的传播机制要做的事务了。
2.1.事务的案例
这里用两个类来演示一个事务的传播
ServiceA:作为事务的发起者,会调用另一个类
ServiceB:被调用者
ClassA
public class ServiceA {
@Autowired
private ServiceB b;
@Transactional
public void methodA() {
// 一坨数据库操作
for(int i = 0; i < 51; i++) {
try {
b.methodB();
} catch(Exception e) {
// 打印异常日志
}
}
// 一坨数据库操作
}
}
ClassB
public class ServiceB {
@Transactional(propagation = PROPAGATION_REQUIRES_NEW)
public void methodB() {
}
}
这里结合两个常用的事务REQUIRED
和REQUIRES_NEW
传播机制,来说明下上面的业务会发生什么
REQUIRED
@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = RuntimeException.class)嵌套的事务是独立的事务,不会影响外面的事务
B会强制开启一个新事务,A的事务会卡主,执行完B的然后执行A的,若A报错,则B不受影响
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = RuntimeException.class)不管methodB()是否加事务,都会使用A的事务,即A或者B中有失败,都整体回滚
REQUIRES_NEW
2.2.事务的传播机制
spring一共定义了7种传播机制。但是我们常用的也就是上面那两种
| 传播机制 | 作用 |
|---|---|
| PROPAGATION_REQUIRED | Spring默认的传播机制,ServiceA.method()-->ServiceB.method,若A和B都声明了事务,则B不会独立开启事务,将B的事务放到A中一起执行,A和B任意一个报错都会整体回滚 |
| PROPAGATION_REQUES_NEW | ServiceB会强制开启一个新的事务,执行的时候ServiceA会卡主等待B执行完毕之后再继续。若A报错,B不受影响,B报错,A可以选择性的回滚或者提交 |
| PROPAGATION_SUPPORT | 如果外层有事务,则加入外层事务,如果外层没有事务,则直接使用非事务方式执行。完全依赖外层的事务 |
| PROPAGATION_NOT_SUPPORT | 该传播机制不支持事务,如果外层存在事务则挂起,执行完当前代码,则恢复外层事务,无论是否异常都不会回滚当前的代码 |
| PROPAGATION_NEVER | 该传播机制不支持外层事务,即如果外层有事务就抛出异常 |
| PROPAGATION_MANDATORY | 与NEVER相反,如果外层没有事务,则抛出异常 |
| PROPAGATION_NESTED | 该传播机制的特点是可以保存状态保存点,当前事务回滚到某一个点,从而避免所有的嵌套事务都回滚,即各自回滚各自的,如果子事务没有把异常吃掉,基本还是会引起全部回滚的。 |
2.3.问题解答
针对开头的spring传播机制的面试题目,可以有如下解答:
A:两个事务都设置为REQUIRED,这个是毋庸置疑的,全部成功或者全部失败 B:将B设置为REQUES_NEW,B每次的调用都在独立事务执行,这样即使第10次失败,也只是回顾最后一次的操作,签名都是独立的事务成功了。
参考资料
spring事务的实现http://www.pladios.top/archives/spring%E4%BA%8B%E5%8A%A1%E7%9A%84%E5%AE%9E%E7%8E%B0
关于我
更多内容可关注公众号
Github: https://github.com/liangliang1259/common-notes 公众号 




