Spring事务管理高层抽象接口为:PlatformTransactionManager。在使用Spring管理事务,需要为不同持久层技术实现,提供不同的事务管理器(即PlatformTransactionManager的实现类),如下:
传播行为不是数据库特性, 解决企业实际开发中事务隔离问题 ---- 解决两个事务互相调用的问题。
一:XML方式配置声明式事务
首先看实际的一个事务配置的例子。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:util="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd ">
<!-- 配置事务管理器 -->
<bean id="cityPickTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="dataSource_backend-product" />
</property>
</bean>
//<tx:annotation-driven transaction-manager="cityPickTransactionManager" /> 这一行不需要
<!-- 配置事务传播特性 -->
<tx:advice id="cityPickAdvice" transaction-manager="cityPickTransactionManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="add*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="create*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="update*" propagation="NESTED"
rollback-for="Exception" />
<tx:method name="batchApply*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="save*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="delete*" propagation="REQUIRED"
rollback-for="Exception" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
<tx:method name="fetch*" propagation="SUPPORTS" read-only="true" />
<tx:method name="is*" propagation="SUPPORTS" read-only="true" />
<tx:method name="*_noTrans" propagation="NOT_SUPPORTED" />
<tx:method name="*byTran" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置参与事务的类 -->
<aop:config>
<aop:pointcut id="cityPickManagerMethod"
expression=" (
execution(* com.test.service.impl.CityPriceScheduleServiceImpl.*(..))
) " />
<aop:advisor advice-ref="cityPickAdvice" pointcut-ref="cityPickManagerMethod" />
</aop:config>
</beans>
需要注意的地方:
(1) advice(建议)的命名:由于每个模块都会有自己的Advice,所以在命名上需要作出规范,初步的构想就是模块名+Advice(只是一种命名规范)。
(2) tx:attribute标签所配置的是作为事务的方法的命名类型。
如<tx:method name="save*" propagation="REQUIRED"/>
其中*为通配符,即代表以save为开头的所有方法,即表示符合此命名规则的方法作为一个事务。
propagation="REQUIRED"代表支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
(3) aop:pointcut标签配置参与事务的类,由于是在Service中进行数据库业务操作,配的应该是包含那些作为事务的方法的Service类。
首先应该特别注意的是id的命名,同样由于每个模块都有自己事务切面,所以我觉得初步的命名规则因为 all+模块名+ServiceMethod。而且每个模块之间不同之处还在于以下一句:
expression="execution(* com.test.testAda.test.model.service.*.*(..))"
其中第一个*代表返回值,第二*代表service下子包,第三个*代表方法名,“(..)”代表方法参数。
(4) aop:advisor标签就是把上面我们所配置的事务管理两部分属性整合起来作为整个事务管理。
图解:
附一、Spring事务类型详解
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop><prop key="store*">PROPAGATION_REQUIRED</prop>
估计有好多朋友还没有弄清楚里面的值的意思,仔细看完下面应该知道自己什么情况下面应该使用什么样的声明。^_^
Spring中常用事务类型:
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
下面是事务的另一种配置方式:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:util="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd ">
<!-- mysql_dataSource -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="mysql_dataSource" />
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="updateMultiGoldCoinPromRuleVoSoldNum">PROPAGATION_REQUIRED,-Exception</prop>
<!-- <prop key="query*">PROPAGATION_REQUIRED,readOnly,-Exception</prop> -->
<prop key="*WithTransaction">PROPAGATION_REQUIRED,-Exception</prop>
</props>
</property>
</bean>
<bean id="transactionBeanNameProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!-- <property name="proxyTargetClass" value="true"/> -->
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
<property name="beanNames">
<list>
<value>goldCoinPromRuleService</value>
</list>
</property>
</bean>
</beans>