[一知半解,就是给自己挖坑]
经过前面两篇的简单叙述,用法演示。本文我们来介绍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配置文件中的下面的这部分内容:
2.下面我们给出上文叙述的配置方式,并解释如何配置相关内容:
3.如果抽象的方式不容易看懂的话,下面我们给出具体配置方式,并解释如何配置相关内容:
<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*等方法后,运行测试即可
-------------------------------------------------------------------------------------------------------------------------------------------------------
最后,我们给出一份常用的配置,供大家参考:
表示:除了上面定义的需求,其他所有的都按照SUPPORTS ,read-only="true" 执行!
--------------------------------------------------------------------------------------------------------------------------------------------------------至此,白话Spring(基础篇)---事务传播行为与隔离级别 结束
备注:
事务是Spring中的核心内容,演示的实例请读者能够成功运行并理解
参考资料:
Spring官网:http://spring.io/docs
Mybatis官方文档:官方文档其他博文:http://jinnianshilongnian.iteye.com/blog/1442376