spring事务方式,传播行为@Transactional
事务:事务就是一组操作数据库动作的集合。如果一组处理步骤全部发生或者一步也不执行,我们称该组处理步骤为一个事务。当所有的步骤像一个操作一样被完整地执行,我们称该事务被提交。如果其中的一部分或多步骤执行失败,导致没有步骤被提交,事务必须回滚到最初的系统状态。
一般我们会在serviceimpl类里面加事务管理
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
事务acid四个特性
1、原子性(Atomicity):事务中包含的操作集合,要么全部操作执行完成,要么全部都不执行。即当事务执行过程中,发生了某些异常情况,如系统崩溃、执行出错,则需要对已执行的操作进行回滚,清除所有执行痕迹。
2、一致性(Consistency):事务执行前和事务执行后,数据库的完整性约束不被破坏。即事务的执行是从一个有效状态转移到另一个有效状态。
3、隔离性(Isolation):多个事务并发执行时,彼此之间不应该存在相互影响。隔离程度不是绝对的,每个数据库都提供有自己的隔离级别,每个数据库的默认隔离级别也不尽相同。
4、持久性(Durability):事务正常执行完毕后,对数据库的修改是永久性的。即事务的修改操作已经记录到了存储介质中。
事务隔离级别,已提交读,未提交读,可重复读,串行化。MySQL默认可重复读,oracle默认已提交读。
两种方式
1、编程式
2、声明式
spring提供了对编程事务和声明事务的支持,编程事务允许用户在代码中精确定义事务的边界,而声明式事务(基于AOP)有助于用户将操作与业务规则进行解耦。
简单地说,编程式事务侵入到了业务代码里面,但是提供了更加详细的事务管理:而声明式事务由于基于AOP,所以既能起到事务管理的作用,有可以不影响业务代码的具体实现。
七种传播方式(propagation)
1、PROPAGATION_REQUIRED(propagation_required)—支持当前事务,如果当前没有事务,就新建一个事务;
方法A调用方法B,如果方法A的已经有开启事务了,那么方法B就不会再新开启事务,而是直接使用方法A的事务,不管双方哪一个执行失败,都会一起回滚。
2、PROPAGATION_REQUIRES_NEW(propagation_requires_new)—新建事务,如果存在当前事务,把当前事务挂起;
方法A调用方法B,就算方法A已经开启了事务,那么方法B也依旧会开启一个新的事务,执行期间将方法A的事务挂起,直到执行完毕之后才开始继续执行方法A,如果方法A执行失败回滚,不会影响到方法B,方法B该提交还是一样提交。
3、PROPAGATION_SUPPORTS(propagation_supports)—支持当前事务,如果没有当前事务,就以非事务方式执行。
此方式比较特殊,是一种随波逐流的方式,如果有它就用,如果没有它就不用。
4、PROPAGATION_NOT_SUPPORTED(propagation_not_supproted)—以非事务方式执行操作,如果当前存在事务,就把当前事务挂起;
不支持事务,如果方法A已经开启了事务,调用方法B时,会将方法A的事务挂起之后开始执行方法B,执行完毕之后继续执行方法A。
5、PROPAGATION_MANDATORY(propagation_mandatory)—支持当前事务,如果当前没有事务,就抛出异常;
强制在一个事务中执行,如果方法A开启了事务,方法B也试图开启一个事务,此时就会直接抛出异常。
6、PROPAGATION_NEVER(propagation_never)—以非事务方式执行,如果当前存在事务,则抛出异常;
不支持事务,如果强制开启事务,或者方法A已经开启了事务,再来调用方法B,就会直接抛出异常。
7、PROPAGATION_NESTED(propagation_nested)—新建事务,依赖于上级事务,如果失败则一同回滚;
这个事务和requires_new很相似,但是不同点在于事务提交的时候,它会让方法B依赖于方法A的事务,B就算开启了事务,也不会主动提交,而是等待A一起提交,此时如果A报错回滚了,那么B也会一起回滚。
注意:spring事务中,默认是只有运行时异常(RuntimeException及其子类)才会回滚,而且使用的默认传播性是REQUIRED。
四种隔离级别(isolation)
隔离级别:未提交读、提交读、可重复读、可串行化