白话Spring(基础篇)---事务传播行为与隔离级别

[一知半解,就是给自己挖坑]

经过前面两篇的简单叙述,用法演示。本文我们来介绍Spring中的事务传播行为,及隔离级别。在这里,我们以日常开发最为推荐的xml配置方式来做为演示,并且在阅读本文之前请先阅读前文中对事务配置的示例工程。

--------------------------------------------------------------------------------------------------------------------------------------------------------

一。事务的嵌套

情景:ServiceA--->ServiceB--->ServiceC。

问题描述:服务调用之间存在层级的关系,并且每一个服务都拥有自己的事务声明。当被调用者的ServiceB,ServiceC执行时,是按照ServiceA调用者的,还是按照自身的声明来执行?

TIP:我们将这种服务调用时的事务关系成为事务嵌套。

--------------------------------------------------------------------------------------------------------------------------------------------------------

二。事务的传播行为:

1.Required:必须有事务,否则创建一个新的事物。如果当前事务存在的话,两个动作将公用一个事务。即如ServiceA--->ServiceB--->ServiceC。A,B,C设置为required后,三者公用一个事务,如果发生错误,三者都将回滚。

2.RequiresNew:每次创建新的事物,即每个动作都是独立事务。当前的事务的成功或失败,都不会对前面的事务的结果造成影响。如果存在嵌套,则需要恢复之前的事务状态。即如ServiceA--->ServiceB--->ServiceC。A,B,C设置为RequiresNew后,三者分别为独立的事务,B,C发生发生异常,不会造成A回滚。

3.Supports:按照当前声明的事务方式执行。即如果当前动作是事务,就按照事务的方式执行,如果是非事务的,就按照非事务方式执行。即ServiceA--->ServiceB--->ServiceC。A是Required,B,C是Supports。则B,C按照Required方式执行

4.NotSupported:即无论当前动作是否是事务的,都会按照非事务的方式执行。特别的,如果存在嵌套到外层事务的动作,将会暂停事务,待完成后在恢复外层事务。ServiceA--->ServiceB--->ServiceC。A是Required,B,C是NotSupported。则B报错。

5.Mandatory:必须存在事务,否则抛出异常(IllegalTransactionStateException)。ServiceA--->ServiceB--->ServiceC。A是Required,B,C是Mandatory。则B报错。

6.Never:不支持事务,如果当前存在是事务则抛出异常(IllegalTransactionStateException)ServiceA--->ServiceB--->ServiceC。A是Required,B,C是Never。则B报错。

7.Nested:嵌套事务支持,如果当前存在事务,则在嵌套事务内执行,如果当前不存在事务,则创建一个新的事务,嵌套事务使用数据库中的保存点来实现,即嵌套事务回滚不影响外部事务,但外部事务回滚将导致嵌套事务回滚。ServiceA--->ServiceB--->ServiceC。A是Required,B,C是Nested。A是事务,B,C在事务内的执行与结束,不影响事务,A直接结束则关闭事务

特别注意:

Nested和RequiresNew的区别:

1、  RequiresNew每次都创建新的独立的物理事务,而Nested只有一个物理事务;

2、  Nested嵌套事务回滚或提交不会导致外部事务回滚或提交,但外部事务回滚将导致嵌套事务回滚,而 RequiresNew由于都是全新的事务,所以之间是无关联的

3、  Nested使用JDBC 3的保存点实现,即如果使用低版本驱动将导致不支持嵌套事务。使用嵌套事务,必须确保具体事务管理器实现的nestedTransactionAllowed属性为true,否则不支持嵌套事务,如DataSourceTransactionManager默认支持,而HibernateTransactionManager默认不支持,需要我们来开启。

--------------------------------------------------------------------------------------------------------------------------------------------------------

三。事务的隔离级别

 ISOLATION_DEFAULT:默认隔离级别,即使用底层数据库默认的隔离级别;

 ISOLATION_READ_UNCOMMITTED:未提交读;

 ISOLATION_READ_COMMITTED:提交读,一般情况下我们使用这个;

 ISOLATION_REPEATABLE_READ:可重复读;

 ISOLATION_SERIALIZABLE:序列化。

----------------------------------------------------------------------------------------------------------------------------------------------------------四。事务超时

概念:设置事务的超时时间,单位为秒,默认为-1表示使用底层事务的超时时间;如果事务超时将抛出org.springframework.transaction.TransactionTimedOutException异常并将当前事务标记为应该回滚,即超时后事务被自动回滚;

用法:使用如setTimeout(100)来设置超时时间,可以使用具体事务管理器实现的defaultTimeout属性设置默认的事务超时时间,如DataSourceTransactionManager. setDefaultTimeout(10)。
----------------------------------------------------------------------------------------------------------------------------------------------------------

五。事务只读

概念:将事务标识为只读,只读事务不修改任何数据; 对于JDBC只是简单的将连接设置为只读模式,对于更新将抛出异常;

对于错误的事务只读设置将抛出IllegalTransactionStateException异常,并伴随“Participating transaction with definition [……] is not marked as read-only……”信息,表示参与的事务只读属性设置错误。

--------------------------------------------------------------------------------------------------------------------------------------------------------

看完了所有的概念,下面实际的演示一个实例来看一下用法及效果吧。

特别说明,本例使用Spring11工程,没有此工程的读者请先查阅前文建立基本工程。

--------------------------------------------------------------------------------------------------------------------------------------------------------

1.找到beans.xml配置文件中的下面的这部分内容:

[html]  view plain  copy
 
  1. <!-- 配置事务通知 -->  
  2.     <tx:advice id="txAdvice" transaction-manager="transactionManager">  
  3.         <tx:attributes>  
  4.             <tx:method name="*"/>  
  5.         </tx:attributes>  
  6.     </tx:advice>  
前面我们是针对所有的方法都设置为事务,显然,在实际开发过程中,是没有必要的。

2.下面我们给出上文叙述的配置方式,并解释如何配置相关内容:

[html]  view plain  copy
 
  1. <tx:advice id="……" transaction-manager="……">    
  2. <tx:attributes>    
  3.         <tx:method name="……"    
  4.                            propagation=" REQUIRED"    
  5.                            isolation="READ_COMMITTED"    
  6.                            timeout="-1"    
  7.                            read-only="false"    
  8.                            no-rollback-for=""     
  9.                            rollback-for=""/>    
  10.         ……    
  11.     </tx:attributes>    
  12. </tx:advice>    

3.如果抽象的方式不容易看懂的话,下面我们给出具体配置方式,并解释如何配置相关内容:

[html]  view plain  copy
 
  1. <!-- 配置事务通知 -->  
  2.     <tx:advice id="txAdvice" transaction-manager="transactionManager">  
  3.         <tx:attributes>  
  4.             <tx:method name="insert*" propagation="REQUIRED" />  
  5.             <tx:method name="update*" propagation="REQUIRED" isolation="READ_COMMITTED" />  
  6.             <tx:method name="save*" propagation="REQUIRED" timeout="-1" />  
  7.             <tx:method name="find*" propagation="REQUIRED" read-only="false"/>  
  8.         </tx:attributes>  
  9.     </tx:advice>  
详细解释:

<tx:advice>:id用于指定此通知的名字, transaction-manager用于指定事务管理器,默认的事务管理器名字为“transactionManager”;<tx:method>:用于定义事务属性即相关联的方法名;

name:定义与事务属性相关联的方法名,将对匹配的方法应用定义的事务属性,可以使用“*”通配符来匹配一组或所有方法,如“save*”将匹配以save开头的方法,而“*”将匹配所有方法;

propagation:事务传播行为定义,默认为“REQUIRED”,表示Required

isolation:事务隔离级别定义;默认为“DEFAULT”
timeout:事务超时时间设置,单位为秒,默认-1,表示事务超时将依赖于底层事务系统;
read-only:事务只读设置,默认为false,表示不是只读;

rollback-for:需要触发回滚的异常定义,以“,”分割,默认任何RuntimeException 将导致事务回滚,而任何Checked Exception 将不导致事务回滚;异常名字定义和TransactionProxyFactoryBean中含义一样

no-rollback-for不被触发进行回滚的 Exception(s);以“,”分割。异常名字定义和TransactionProxyFactoryBean中含义一样

-------------------------------------------------------------------------------------------------------------------------------------------------------

关于这些配置的运行结果,请读者自行替换配置文件的内容,及完善save*,insert*等方法后,运行测试即可

-------------------------------------------------------------------------------------------------------------------------------------------------------

最后,我们给出一份常用的配置,供大家参考:

[html]  view plain  copy
 
  1. <tx:advice id="txAdvice" transaction-manager="txManager">    
  2. <tx:attributes>    
  3.            <tx:method name="save*" propagation="REQUIRED" />    
  4.            <tx:method name="add*" propagation="REQUIRED" />    
  5.            <tx:method name="create*" propagation="REQUIRED" />    
  6.            <tx:method name="insert*" propagation="REQUIRED" />    
  7.            <tx:method name="update*" propagation="REQUIRED" />    
  8.            <tx:method name="merge*" propagation="REQUIRED" />    
  9.            <tx:method name="del*" propagation="REQUIRED" />    
  10.            <tx:method name="remove*" propagation="REQUIRED" />    
  11.            <tx:method name="put*" propagation="REQUIRED" />    
  12.            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />    
  13.            <tx:method name="count*" propagation="SUPPORTS" read-only="true" />    
  14.           <tx:method name="find*" propagation="SUPPORTS" read-only="true" />    
  15.           <tx:method name="list*" propagation="SUPPORTS" read-only="true" />    
  16.           <tx:method name="*" propagation="SUPPORTS" read-only="true" />    
  17.        </tx:attributes>    
  18. </tx:advice>    
  19. <aop:config>    
  20.        <aop:pointcut id="txPointcut" expression="execution(* com.java.ingo..service.*.*(..))" />    
  21.        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />    
  22. </aop:config>    
备注:

[html]  view plain  copy
 
  1. <tx:method name="*" propagation="SUPPORTS" read-only="true" />   

表示:除了上面定义的需求,其他所有的都按照SUPPORTS ,read-only="true" 执行!
--------------------------------------------------------------------------------------------------------------------------------------------------------至此,白话Spring(基础篇)---事务传播行为与隔离级别 结束

备注:

事务是Spring中的核心内容,演示的实例请读者能够成功运行并理解


参考资料:

Spring官网:http://spring.io/docs

Mybatis官方文档:官方文档

其他博文:http://jinnianshilongnian.iteye.com/blog/1442376

你可能感兴趣的:(spring,事务,Bean配置,传播属性,隔离界别)