Spring事务服务
<h2 id="t_655974a60101cd0v" class="titName SG_txta">Spring事务服务</h2>
<span class="img2">
<img width="15" height="15" align="absmiddle" title="此博文包含图片" src="http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif" class="SG_icon SG_icon18">
</span>
<span class="time SG_txtc">(2013-07-22 11:13:36)</span><div class="turnBoxzz"><a href="javascript:;" class="SG_aBtn SG_aBtn_ico SG_turn" action-type="reblog" action-data="{srcBlog:1, blogId:'655974a60101cd0v'}"><cite><img class="SG_icon SG_icon111" src="http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif" width="15" height="15" align="absmiddle">转载<em class="arrow">▼</em></cite></a></div> </div>
<div class="articalTag" id="sina_keyword_ad_area">
<table>
<tbody><tr>
<td class="blog_tag">
<script>
var $tag='事务管理,ssh';
var $tag_code='93fa4cee78f86e99e7c8f0b200a6b714';
var $r_quote_bligid='655974a60101cd0v';
var $worldcup='0';
var $worldcupball='0';
</script>
<span class="SG_txtb">标签:</span>
<h3><a href="http://search.sina.com.cn/?c=blog&q=%CA%C2%CE%F1%B9%DC%C0%ED&by=tag" target="_blank">事务管理</a></h3>
<h3><a href="http://search.sina.com.cn/?c=blog&q=ssh&by=tag" target="_blank">ssh</a></h3>
</td>
<td class="blog_class">
<span class="SG_txtb">分类:</span>
<a target="_blank" href="http://blog.sina.com.cn/s/articlelist_1700361382_4_1.html">Sping</a>
</td>
</tr>
</tbody></table>
</div>
<!-- 正文开始 -->
<div id="sina_keyword_ad_area2" class="articalContent ">
<p>
Spring为事务管理提供了一流的支持。同时支持编程式事务和声明式事务。无论是编程式事务,还是声明式事务,在开发Spring应用工程中,开发者都不需要同具体的事务管理实现进行交互。
数据库事务
通常,数据库事务都具备ACID的特性。
对于声明式事务,Spring支持各种事务管理器,它提供TransactionProxyFactoryB
对于编程式事务,Spring也支持各种事务管理器,而且,比声明式事务更灵活。
在Spring提供的所有事务管理器中,PlatformTransactionManag
开发者应该很清楚,Spring框架肯定会为它提供若干个实现,供Spring
IOC实现控制反转使用。对于Hiberante,需要借助于 HiberanteTransactionMana
<bean id=”transactionManager”
class=”org.springframework.orm.hibernate.HibernateTransactionMana
<property name=”sessionFactory”>
</property>
HibernateTransactionMana
Spring主要涉及到的事务管理器有:
●
●
●
●
●
●
对于JDBC事务而言,需要配置DataSourceTransactionMan
<bean id=”transactionManager”
class=”org.springframework.jdbc.datasource.DataSourceTransactionMan
<property name=”dataSource”>
<ref local=”dataSource”/>
class=”org.springframework.jndi.JndiObjectFactoryBean”>
开发者需要为它准备dataSource
取值。至于dataSource的具体来源,DataSourceTransactionMan
对于JDO事务而言,需要配置JdoTransactionManager。配置如下:
<bean id=”transactionManager”
class=”org.springframework.orm.jdo.JdoTransactionManager”>
<property
name=”persistenceManagerFactor
<ref
local=”persistenceManagerFactor
对于JTA事务而言,需要配置JtaTransactionManager或者WebLogicJtaTransactionMa
<bean id=”transactionManager”
class=”org.springframework.transaction.jta.JtaTransactionManager”>
<property name=”userTransactionName”>
<value>java:comp/UserTransaction</value>
其中,指定了userTransactionName
属性。默认时,JtaTransactionManager设定userTransactionName属性取值为java:comp/UserTransaction,因此如果目标JTA实现的UserTransaction
名为java:comp/UserTransaction,则不用给出userTransactionName属性。当然,除了userTransactionName
属性外,还具有transactionManagerName、jndiTemplate、autodetectTransactionMan
声明式事务
借助Spring AOP,Spring提供了
TransactionProxyFactoryB
使用声明式事务管理器,首先要搭建SSH框架,添加 Spring AOP JAR包,添加方法详见上篇:http://blog.sina.com.cn/s/blog_655974a60101c891.html#bsh-75-262512748
事务配置
首先在/WEB-INF/applicationContext.xml添加以下内容:
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionMana
</bean>
注:这是作为公共使用的事务管理器Bean。这个会是事先配置好的,不需各个模块各自去配。
下面就开始配置各个模块所必须的部分,在各自的applicationContext-XXX-beans.xml配置的对于事务管理的详细信息。
首先就是配置事务的传播特性,如下:
<!--
<tx:advice id="TestAdvice" transaction-manager="transactionManager">
</tx:advice>
<!--
<aop:config>
<aop:pointcut id="allTestServiceMethod" expression="execution(* com.test.testAda.test.model.service.*.*(..))"/>
<aop:advisor pointcut-ref="allTestServiceMethod" advice-ref="TestAdvice" />
</aop:config>
事务的几种传播特性
1. PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启
2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
3. PROPAGATION_MANDATORY: 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
4. PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
5. PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
6. PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常
7. PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务,则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行
需要注意的地方:
(1) advice(建议)的命名:由于每个模块都会有自己的Advice,所以在命名上需要作出规范,初步的构想就是模块名+Advice(只是一种命名规范)。
(2) tx:attribute标签所配置的是作为事务的方法的命名类型。
(3) aop:pointcut标签配置参与事务的类,由于是在Service中进行数据库业务操作,配的应该是包含那些作为事务的方法的Service类。
(4) aop:advisor标签就是把上面我们所配置的事务管理两部分属性整合起来作为整个事务管理。
图解:
下面给出详细的applicationContext.xml 文件的注释:
<?xml version="1.0"
encoding="gb2312"?>
<!--
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean
id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
local="dataSource"/></property>
<!--以下用来列出所有的PO映射文件-->
<value>Person.hbm.xml</value>
<!--此处用来定义hibernate的SessionFactory的属性:
不同数据库连接,启动时选择create,update,create-drop-->
key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
key="hibernate.hbm2ddl.auto">update</prop>
id="transactionManager"
bean的引用-->
local="sessionFactory"/></property>
作为事务代理的目标-->
bean注入SessionFactory引用-->
local="sessionFactory"/></property>
bean的事务代理-->
bean="transactionManager"/></property>
name="transactionAttributes">
<props>
<prop key="find">PROPAGATION_REQUIRED,readOnly</prop>
->
key="
</props>
-->
name="target">
local="personDaoTarget"/>
</beans>
在上面的配置文件中,personDao需要配置两个部分,一个是personDao的目标bean,该目标bean是实际DAO
bean,以实际的DAO bean为目标,建立事务代理。一个组件,需要来个bean组成,一个目标bean,一个事务代理。
这种配置方式还有一个坏处:目标bean直接暴露在Spring容器中,可以直接引用,如果目标bean被误引用,将导致业务操作不具备事务性。
为了避免这种现象,可将目标bean配置成嵌套bean,下面是目标bean和事务代理的配置片段:
<!--
bean的事务代理-->
id="personDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryB
name="transactionManager"><ref
bean="transactionManager"/></property>
name="transactionAttributes">
key="find*">PROPAGATION_REQUIRED,readOnly</prop>
->
key="*">PROPAGATION_REQUIRED</prop>
-->
name="target">
class="lee.PersonDaoHibernate">
bean注入SessionFactory引用-->
local="sessionFactory"/></property>
</bean>