spring事务传播机制

上传人:xiao****1972 文档编号:84903533 上传时间:2019-03-05 格式:DOC 页数:5 大小:42.50KB
返回 下载 相关 举报
spring事务传播机制_第1页
第1页 / 共5页
spring事务传播机制_第2页
第2页 / 共5页
spring事务传播机制_第3页
第3页 / 共5页
spring事务传播机制_第4页
第4页 / 共5页
spring事务传播机制_第5页
第5页 / 共5页
亲,该文档总共5页,全部预览完了,如果喜欢就下载吧!
资源描述

《spring事务传播机制》由会员分享,可在线阅读,更多相关《spring事务传播机制(5页珍藏版)》请在金锄头文库上搜索。

1、Spring事务传播机制解惑概述当我们调用一个基于Spring的Service接口方法(如UserService#addUser())时,它将运行于Spring管理的事务 环境中,Service接口方法可能会在内部调用其它的Service接口方法以共同完成一个完整的业务操作,因此就会产生服务接口方法嵌套调用的情况, Spring通过事务传播行为控制当前的事务如何传播到被嵌套调用的目标服务接口方法中。事务传播是Spring进行事务管理的重要概念,其重要性怎么强调都不为过。但是事务传播行为也是被误解最多的地方,在本文里,我们将详细分析不同事务传播行为的表现形式,掌握它们之间的区别。事务传播行为种类

2、Spring在TransactionDefinition接口中规定了7种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播:表1事务传播行为类型事务传播行为类型说明PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。PROPAGATION_MANDATORY使用当前的事务,如果当前没有事务,就抛出异常。PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。P

3、ROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。当使用PROPAGATION_NESTED时,底层的数据源必须基于JDBC 3.0,并且实现者需要支持保存点事务机制。几种容易引起误解的组合事务传播行为当服务接口方法分别使用表1中不同的事务传播行为,且这些接口方法又发生相互调用的情况下,大部分组合都是一目了然

4、,容易理解的。但是,也存在一些容易引起误解的组合事务传播方式。下面,我们通过两个具体的服务接口的组合调用行为来破解这一难点。这两个服务接口分别是UserService和ForumService, UserSerice有一个addCredits()方法,ForumSerivce#addTopic()方法调用了 UserSerice#addCredits()方法,发生关联服务方法的调用:public class ForumService private UserService userService;public void addTopic()调用其它服务接口的方法/add TopicuserSe

5、rvice.addCredits();被关联调用的业务方法嵌套调用的事务方法对Spring事务传播行为最常见的一个误解是:当服务接口方法发生嵌套调用时,被调用的服务方法只能声明为 PROPAGATION_NESTED。这种观点犯了望文生义的错误,误认为PROPAGATION_NESTED是专为方法嵌套准备的。这种误解遗害不 浅,执有这种误解的开发者错误地认为:应尽量不让Service类的业务方法发生相互的调用,Service类只能调用DAO层的DAO类,以避免产生嵌 套事务。其实,这种顾虑是完全没有必要的,PROPAGATION_REQUIRED已经清楚地告诉我们:事务的方法会足够“聪明”地判

6、断上下文是否已经存在一个事务中,如果已经存在,就加入到这个事务中,否则创建一个新的事务。依照上面的例子,假设我们将ForumService#addTopic()和UserSerice#addCredits()方法的事务传播行为都设置为PROPAGATION_REQUIRED,这两个方法将运行于同一个事务中。为了清楚地说明这点,可以将Log4J的日志设置为DEBUG级别,以观察Spring事务管理器内部的运行情况。下面将两个业务方法都设置为PROPAGATION_REQUIRED,Spring所输出的日志信息如下:Using transaction object org.springframew

7、ork.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObjecte3849c为ForumService#addTopic()新建一个事务Creating new transaction with name com.baobaotao.service.ForumService.addTopic: PROPAGATION_REQUIRED,ISOLATION_DEFAULTAcquired Connection mons.dbcp.PoolableConnectiondc41c5 for JDBC transa

8、ctionSwitching JDBC Connection mons.dbcp.PoolableConnectiondc41c5 to manual commitBound value org.springframework.jdbc.datasource.ConnectionHolderee1ede for key mons.dbcp.BasicDataSource4204 to thread mainInitializing transaction synchronizationGetting transaction for com.baobaotao.service.ForumServ

9、ice.addTopicRetrieved value org.springframework.jdbc.datasource.ConnectionHolderee1ede for key mons.dbcp.BasicDataSource4204 bound to thread mainUsing transaction object org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject8b8a47UserService#addCredits()简单地加入到已存

10、在的事务中(即处创建的事务)Participating in existing transactionGetting transaction for com.baobaotao.service.UserService.addCreditsCompleting transaction for com.baobaotao.service.UserService.addCreditsCompleting transaction for com.baobaotao.service.ForumService.addTopicTriggering beforeCommit synchronizationT

11、riggering beforeCompletion synchronizationInitiating transaction commit调用底层Connection#commit()方法提交事务Committing JDBC transaction on Connection mons.dbcp.PoolableConnectiondc41c5Triggering afterCommit synchronizationTriggering afterCompletion synchronizationClearing transaction synchronization嵌套事务将For

12、umService#addTopic()设置为PROPAGATION_REQUIRED时, UserSerice#addCredits()设置为PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS、 PROPAGATION_MANDATORY时,运行的效果都是一致的(当然,如果单独调用addCredits()就另当别论了)。当addTopic()运行在一个事务下(如设置为PROPAGATION_REQUIRED),而addCredits()设置为 PROPAGATION_NESTED时,如果底层数据源支持保存点,Spring将为内部的addCredits()方法产

13、生的一个内嵌的事务。如果 addCredits()对应的内嵌事务执行失败,事务将回滚到addCredits()方法执行前的点,并不会将整个事务回滚。内嵌事务是内层事务的一 部分,所以只有外层事务提交时,嵌套事务才能一并提交。嵌套事务不能够提交,它必须通过外层事务来完成提交的动作,外层事务的回滚也会造成内部事务的回滚。嵌套事务和新事务PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED也是容易混淆的两个传播行为。PROPAGATION_REQUIRES_NEW 启动一个新的、和外层事务无关的“内部”事务。该事务拥有自己的独立隔离级别和锁,不依赖于外部事务,独

14、立地提交和回滚。当内部事务开始执行时,外部事务 将被挂起,内务事务结束时,外部事务才继续执行。由此可见, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于:PROPAGATION_REQUIRES_NEW 将创建一个全新的事务,它和外层事务没有任何关系,而 PROPAGATION_NESTED 将创建一个依赖于外层事务的子事务,当外层事务提交或回滚时,子事务也会连带提交和回滚。其它需要注意问题以下几个问题值得注意:1) 当业务方法被设置为PROPAGATION_MANDATORY时,它就不能被非事务的业务方法调用。如将ForumServ

15、ice#addTopic ()设置为PROPAGATION_MANDATORY,如果展现层的Action直接调用addTopic()方法,将引发一个异常。正确的情况是: addTopic()方法必须被另一个带事务的业务方法调用(如ForumService#otherMethod())。所以 PROPAGATION_MANDATORY的方法一般都是被其它业务方法间接调用的。2) 当业务方法被设置为PROPAGATION_NEVER时,它将不能被拥有事务的其它业务方法调用。假设UserService#addCredits ()设置为PROPAGATION_NEVER,当ForumService# addTopic()拥有一个事务时,addCredits()方法将抛出异常。所以PROPAGATION_NEVER方法一般是被直接调用的。3)当方法被设置为PROPAGATION_NOT_SUPPORTED时,外层业务方法的事务会被挂起,当内部方法运行完成后,外层方法的事务重新运行。如果外层方法没有事务,直接运行,不需要做任何其它的事。小结在Spring声明式事务管理的配置中,事务传播行为是最容易被误解的配置项,原因在于事务传播行为名称

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 大杂烩/其它

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号