5、事务管理
(1)事务
l 全局事务
Ø 由应用服务器使用JTA管理
Ø 具有同多事务资源工作的能力
l 本地事务
Ø 资源规范:如和JDBC连接关联的事务
Ø 不能够在多事务资源之间交叉工作
Ø 不能在全局的JTA事务中运行
l 不同的编程模型
(2)Spring解决方案
l 对全局和本地事务使用相同的编程模型
Ø 不同的环境采用不同的事务管理策略
l 事务管理可以:
Ø 编程方式
Ø 声明方式(如EJB CMT)
(3)事务提取
l 事务通过PlatformTransactionManager接口提取
Ø getTransaction(TransactionDefinition)
Ø commit(TransactionStatus)
Ø rollback(TransactionStatus)
l TransactionDefinition:隔离、传播、超时和只读状态
l TransactionStatus
Ø isNewTransaction()
Ø setRollbackOnly()
Ø isRollbackOnly()
(4)事务管理
l 内建平台事务管理:
Ø JtaTransacrionManager
Ø DataSourceTransacrionManager
Ø HibernateTransacrionManager
Ø JdoTransacrionManager
(5)例子
l 定义一个JtaTransacrionManager
<bean id="dataSource" class="...jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>MyDS</value></property>
</bean>
<bean id="transactionManager"
class="...transaction.jta.JtaTransactionManager"/>
数据源必须在应用服务器中被配置为事务资源
l 定义一个DataSourceTransacrionManager
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
...
</bean>
<bean id="transactionManager"
class="...jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local="dataSource"/>
</property>
</bean>
l 定义一个HibernateTransacrionManager
<bean id="sessionFactory"
class="...orm.hibernate.LocalSessionFactoryBean">
...
</bean>
<bean id="transactionManager"
class="...orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
使用JTA来应用Hibernate不需要HibernateTransacrionManager,只要配置JtaTransacrionManager,给出从JNDI获得的sessionFactory数据源
(6)TransactionTemplate
l 编程方式的事务管理
l 创建一个TransactionTemplate
PlatformTransactionManager transactionManager =
(PlatformTransactionManager) ctx.getBean("myTransactionManager");
TransactionTemplate transaction =
new TransactionTemplate(transactionManager);
l 在一个事务中执行
transaction.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus s) {
updateOperation1();
updateOperation2();
}
});
l TransactionTemplate的其它方法
Ø setPropagationBehavior(int)
Ø setIsolationLevel(int)
Ø setReadOnly(Boolean)
Ø setTimeout(int)
(7)好处
l 不同事务管理之间转换
Ø 只是一些配置
Ø 不需要改变代码
l 相同的组件可以运行在:
Ø 使用JTA事务的应用服务器
Ø 独立应用程序或Web容器:使用JDBC或开源JTA(如JOTM)
(8)声明式事务
l 不需要TransactionTemplate
l 使用Spring AOP实现
l 类似于EJB CMT:指定事务行为到独立的方法
l 和EJB CMT的区别:
Ø 能够应用到任何的POJO
Ø 不需要绑定到JTA(可以和JDBC、JDO和Hibernate一起工作)
Ø 具有声明式rollback规则
Ø 定制事务行为
Ø 不需要支持通过远程调用来传播事务context
(9)TransactionAttributeSource
l 定义事务属性如何应用
l TransactionAttributeEditor读取下面形式的定义:
Ø PROPAGATION_NAME、ISOLATION_NAME、readOnly、+Exception1、-Exception2
Ø 异常名前面的+表示即使异常抛出,也要提交(commit);异常名前面的-表示需要回滚(rollback)
l 例子:
Ø PROPAGATION_MANDATORY、ISOLATION_DEFAULT、-CreateException、-DuplicateKeyException
(10)声明事务
l 定义事务拦截器
<bean id="txAttributes"
class="...MatchAlwaysTransactionAttributeSource">
<property name="transactionAttribute">
<value>PROPAGATION_REQUIRED</value>
</property>
</bean>
<bean id="txInterceptor"
class="...transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="myTransactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref bean="txAttributes"/>
</property>
</bean>
MatchAlwaysTransactionAttributeSource应用相同的属性到所有的方法
l 可变的TransactionAttributeSource
<bean id="txAttributes"
class="...interceptor.NameMatchTransactionAttributeSource">
<property name="properties">
<value>
get*=PROPAGATION_REQUIRED,readOnly
find*=PROPAGATION_REQUIRED,readOnly
load*=PROPAGATION_REQUIRED,readOnly
store*=PROPAGATION_REQUIRED
</value>
</property>
</bean>
NameMatchTransactionAttributeSource应用特定的属性到匹配的方法
l 自动代理事务Beans
<bean id="autoProxyCreator"
class="...framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<value>txInterceptor</value>
</property>
<property name="beanNames">
<value>*Dao</value>
</property>
</bean>
l 使用元数据属性
<bean id="autoproxy"
class="...aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
</bean>
<bean id="txAdvisor"
class="...transaction.interceptor.TransactionAttributeSourceAdvisor"
autowire="constructor">
</bean>
<bean id="txInterceptor"
class="...transaction.interceptor.TransactionInterceptor"
autowire="byType">
</bean>
<bean id="txAttributeSource"
class="...transaction.interceptor.AttributesTransactionAttributeSource"
autowire="constructor">
</bean>
<bean id="attributes"
class="...metadata.commons.CommonsAttributes">
</bean>