Spring事务的传播机制
Spring提供了事务的注解
属性propagation [ˌprɒpə'ɡeɪʃ(ə)n] 传播
一共有7种事务传播机制
下面通过a.save()调用b.save()解释事务的传播机制
REQUIRED:(必须的)Spring的默认传播级别,如果上下文中存在事务则加入当前事务,如果不存在事务则新建事务执行。
PS:a.save和b.save的事务传播机制都是REQUIRED,b.save的事务是跟着a.save的;若a.save没有事务,b.save的传播机制为REQUIRED,则b.save出现异常会回滚
SUPPORTS:(支持)如果上下文中存在事务则加入当前事务,如果没有事务则以非事务方式执行。
PS:若a.save开启了事务则b.save就有事务,若a.save没有事务,b.save的事务传播机制为SUPPORTS,那么b.save也没有事务-出现异常不会回滚。
MANDATORY:([ˈmændətəri] 强制的)该传播级别要求上下文中必须存在事务,否则抛出异常。
PS:当b.save的事务传播机制为MANDATORY时,如果a.save不开启事务,则会抛出下面的异常
REQUIRES_NEW:(开启新的事务)该传播级别每次执行都会创建新事务,并同时将上下文中的事务挂起,执行完当前线程后再恢复上下文中事务。(子事务的执行结果不影响父事务的执行和回滚)
PS:当b.save的事务传播机制为REQUIRES_NEW时,a.save发生异常(a.save会回滚),但是不会影响b.save的事务提交,也就是b.save正常执行;b.save发生了异常,b的事务会回滚,但不会影响a.save的事务
NOT_SUPPORTED:(不支持事务)当上下文中有事务则挂起当前事务,执行完当前逻辑后再恢复上下文事务。(降低事务大小,将非核心的执行逻辑包裹执行。)
PS:当a.save开启事务,b.save的事务传播机制为NOT_SUPPORTED时,b.save是不支持事务的,b.save发生异常不会回滚,但是不会影响a.save的事务,所以a.save会回滚
NEVER:(绝不要事务)该传播级别要求上下文中不能存在事务,否则抛出异常。
PS:当a.save开启事务,但是b.save的事务传播机制为NEVER时,则会抛出下面的异常
NESTED:嵌套事务,如果上下文中存在事务则嵌套执行,如果不存在则新建事务。(save point概念)
Nested和RequiresNew的区别:
- RequiresNew每次都创建新的独立的物理事务,而Nested只有一个物理事务;Nested嵌套事务回滚或提交不会导致外部事务回滚或提交,但外部事务回滚将导致嵌套事务回滚,而RequiresNew由于都是全新的事务,所以之间是无关联的
- Nested使用JDBC 3的保存点实现,即如果使用低版本驱动将导致不支持嵌套事务
使用嵌套事务,必须确保具体事务管理器实现的nestedTransactionAllowed属性为true,否则不支持嵌套事务,如DataSourceTransactionManager默认支持,而HibernateTransactionManager默认不支持,需要我们来开启。
Spring 是如何管理事务的?
Spring事务管理主要包括3个接口,Spring的事务主要是由它们(PlatformTransactionManager,TransactionDefinition,TransactionStatus)三个共同完成的。
1. PlatformTransactionManager:事务管理器--主要用于平台相关事务的管理
主要有三个方法:
- commit 事务提交;
- rollback 事务回滚;
- getTransaction 获取事务状态。
2. TransactionDefinition:事务定义信息--用来定义事务相关的属性,给事务管理器PlatformTransactionManager使用
这个接口有下面四个主要方法:
- getIsolationLevel:获取隔离级别;
- getPropagationBehavior:获取传播行为;
- getTimeout:获取超时时间;
- isReadOnly:是否只读(保存、更新、删除时属性变为false--可读写,查询时为true--只读)
事务管理器能够根据这个返回值进行优化,这些事务的配置信息,都可以通过配置文件进行配置。
3. TransactionStatus:事务具体运行状态--事务管理过程中,每个时间点事务的状态信息。
例如它的几个方法:
- hasSavepoint():返回这个事务内部是否包含一个保存点,
- isCompleted():返回该事务是否已完成,也就是说,是否已经提交或回滚
- isNewTransaction():判断当前事务是否是一个新事务
声明式事务的优缺点:
- 优点:不需要在业务逻辑代码中编写事务相关代码,只需要在配置文件配置或使用注解(@Transaction),这种方式没有侵入性。
- 缺点:声明式事务的最细粒度作用于方法上,如果像代码块也有事务需求,只能变通下,将代码块变为方法。
劈天造陆,开辟属于自己的天地!!!与君共勉