读书人

Spring 9.3 编程式事宜

发布时间: 2012-10-24 14:15:58 作者: rapoo

Spring 9.3 编程式事务
java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:

图9-2 Required传播行为

?Spring 9.3  编程式事宜

图9-3 Required传播行为抛出异常情况

????????????? 在前边示例中就是使用的Required传播行为:

一、在调用userService对象的save方法时,此方法用的是Required传播行为且此时Spring事务管理器发现还没开启逻辑事务,因此Spring管理器觉得开启逻辑事务,

二、在此逻辑事务中调用了addressService对象的save方法,而在save方法中发现同样用的是Required传播行为,因此使用该已经存在的逻辑事务;

三、在返回到addressService对象的save方法,当事务模板类执行完毕,此时提交并关闭事务。

?????? 因此userService对象的save方法和addressService的save方法属于同一个物理事务,如果发生回滚,则两者都回滚。

?

?

接下来测试一下该传播行为如何执行吧:

一、正确提交测试,如上一节的测试,在此不再演示;

二、回滚测试,修改AddressServiceImpl的save方法片段:

?

java代码:java代码:java代码:java代码:java代码:java代码:

图9-4 RequiresNew传播行为

?Spring 9.3  编程式事宜

图9-5 RequiresNew传播行为并抛出异常

接下来测试一个该传播行为如何执行吧:

1、将如下获取事务模板方式

?

java代码:java代码:java代码:java代码:java代码:java代码:java代码:

图9-6 Required+Supports传播行为

?Spring 9.3  编程式事宜

?????? 图9-7 Supports+Supports传播行为

?

?

?

?

NotSupported:不支持事务,如果当前存在事务则暂停该事务,使用PROPAGATION_NOT_SUPPORTED指定,即以非事务方式执行,如果当前存在逻辑事务,就把当前事务暂停,以非事务方式执行,如图9-8和9-9所示:

?Spring 9.3  编程式事宜

?????? 图9-8 Required+NotSupported传播行为

?Spring 9.3  编程式事宜

?????? 图9-9 Supports+NotSupported传播行为

?

?

?

?

Mandatory:必须有事务,否则抛出异常,使用PROPAGATION_MANDATORY指定,使用当前事务执行,如果当前没有事务,则抛出异常(IllegalTransactionStateException),如图9-10和9-11所示:

?

?

?Spring 9.3  编程式事宜

?????? 图9-10 Required+Mandatory传播行为

?Spring 9.3  编程式事宜

?????? 图9-11 Supports+Mandatory传播行为

?

?

?

?

Never:不支持事务,如果当前存在是事务则抛出异常,使用PROPAGATION_NEVER指定,即以非事务方式执行,如果当前存在事务,则抛出异常(IllegalTransactionStateException),如图9-12和9-13所示:

?Spring 9.3  编程式事宜

?????? 图9-12 Required+Never传播行为

?Spring 9.3  编程式事宜

?????? 图9-13 Supports+Never传播行为

?

?

?

?

?

Nested:嵌套事务支持,使用PROPAGATION_NESTED指定,如果当前存在事务,则在嵌套事务内执行,如果当前不存在事务,则创建一个新的事务,嵌套事务使用数据库中的保存点来实现,即嵌套事务回滚不影响外部事务,但外部事务回滚将导致嵌套事务回滚,如图9-14和9-15所示:

?Spring 9.3  编程式事宜

?????? 图9-14 Required+Nested传播行为

?Spring 9.3  编程式事宜

图9-15 Nested+Nested传播行为

?

?

?

Nested和RequiresNew的区别:

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

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

3、? Nested使用JDBC 3的保存点实现,即如果使用低版本驱动将导致不支持嵌套事务。

使用嵌套事务,必须确保具体事务管理器实现的nestedTransactionAllowed属性为true,否则不支持嵌套事务,如DataSourceTransactionManager默认支持,而HibernateTransactionManager默认不支持,需要我们来开启。

对于事务传播行为我们只演示了Required和RequiresNew,其他传播行为类似,如果对这些事务传播行为不太会使用,请参考chapter9包下的TransactionTest测试类中的testPropagation方法,方法内有详细示例。

?

事务超时:设置事务的超时时间,单位为秒,默认为-1表示使用底层事务的超时时间;

? ? ? ? ?使用如setTimeout(100)来设置超时时间,如果事务超时将抛出org.springframework.transaction.TransactionTimedOutException异常并将当前事务标记为应该回滚,即超时后事务被自动回滚;

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

?

事务只读:将事务标识为只读,只读事务不修改任何数据;

? ? ? ? ?对于JDBC只是简单的将连接设置为只读模式,对于更新将抛出异常;

? ? ? ? ?而对于一些其他ORM框架有一些优化作用,如在Hibernate中,Spring事务管理器将执行“session.setFlushMode(FlushMode.MANUAL)”即指定Hibernate会话在只读事务模式下不用尝试检测和同步持久对象的状态的更新。

? ? ? ? ?如果使用设置具体事务管理的validateExistingTransaction属性为true(默认false),将确保整个事务传播链都是只读或都不是只读,如图9-16是正确的事务只读设置,而图9-17是错误的事务只读设置:

?Spring 9.3  编程式事宜

图9-16 正确的事务只读设置

?

?Spring 9.3  编程式事宜

图9-17 错误的事务只读设置

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

?

?

大家有没有感觉到编程式实现事务管理是不是很繁琐冗长,重复,而且是侵入式的,因此发展到这Spring决定使用配置方式实现事务管理。

??9.3.6? 配置方式实现事务管理

在Spring2.x之前为了解决编程式事务管理的各种不好问题,Spring提出使用配置方式实现事务管理,配置方式利用代理机制实现,即使有TransactionProxyFactoryBean类来为目标类代理事务管理。

?

接下来演示一下具体使用吧:

1、重新定义业务类实现,在业务类中无需显示的事务管理代码:

?

java代码:java代码:java代码:java代码:java代码:java代码:java代码:java代码:

图9-18 代理方式实现事务管理

?????? 如图9-18,代理方式实现事务管理只是将硬编码的事务管理代码转移到代理中去由代理实现,在代理中实现事务管理。

?

?????? 注:在代理模式下,默认只有通过代理对象调用的方法才能应用相应的事务属性,而在目标方法内的“自我调用”是不会应用相应的事务属性的,即被调用方法不会应用相应的事务属性,而是使用调用方法的事务属性。

?

如图9-19所示,在目标对象targetUserService的save方法内调用事务方法“this.otherTransactionMethod()”将不会应用配置的传播行为RequriesNew,开启新事务,而是使用save方法的已开启事务,如果非要这样使用如下方式实现:

?

1、? 修改TransactionProxyFactoryBean配置定义,添加exposeProxy属性为true;

2、? 在业务方法内通过代理对象调用相应的事务方放,如 “((IUserService)AopContext.currentProxy()).otherTransactionMethod()”即可应用配置的事务属性。

3、? 使用这种方式属于侵入式,不推荐使用,除非必要。

Spring 9.3  编程式事宜?

图9-19 代理方式下的自我调用

?

?????? 配置方式也好麻烦啊,每个业务实现都需要配置一个事务代理,发展到这,Spring想出更好的解决方案,Spring2.0及之后版本提出使用新的“<tx:tags/>”方式配置事务,从而无需为每个业务实现配置一个代理。

?

?

原创内容,转载请注明出处【http://sishuok.com/forum/blogPost/list/2506.html】

读书人网 >编程

热点推荐