spring 比较实用的事物管理

来源:互联网 发布:dota2孽主技能数据值 编辑:程序博客网 时间:2024/05/15 23:52

          事物管理:这个有点抽象,书面表达是这样的:

 

为了完成对数据的操作,企业应用经常要求并发访问在多个构件之间共享的数据。这些应用在下列条件下应该维护数据的完整性(由应用的商务规则来定义): 分布式访问一个单独的数据资源,以及从一个单独的应用构件访问分布式资源。 在这种情况,可能要求在(分布式)资源上的一组操作被当作一个工作单元(unit)。在一个工作单元中, 操作的所有部分一起成功或失败并恢复。在下面的情况下这个问题更加复杂: 通过一组分布式的、访问多个资源的数据的构件实现一个工作单元,和/或部分操作是被顺序执行的或在要求协调和/或同步的并行线程中。 在所有情况下, 都要求应用维护一个工作单元的成功或失败。在失败的情况下,所有资源要把数据状态返回到以前的状态 (比如说,工作单元开始前的状态)。 事务的概念和和事务管理器(或者一个事务处理服务)在一个工作单元中的维护数据完整性,这就简化了这样的企业级别分布式应用的构造。 一个事务是有下列属性的一个工作单元: 原子性(ATOMICITY): 一个事务要被完全的无二义性的做完或撤消。在任何操作出现一个错误的情况下,构成事务的所有操作的效果必须被撤消,数据应被回滚到以前的状态。 一致性(CONSISTENCY): 一个事务应该保护所有定义在数据上的不变的属性(例如完整性约束)。在完成了一个成功的事务时,数据应处于一致的状态。换句话说,一个事务应该把系统从一个一致-状态转换到另一个一致状态。举个例子,在关系数据库的情况下, 一个一致的事务将保护定义在数据上的所有完整性约束。 隔离性(ISOLATION): 在同一个环境中可能有多个事务并发执行,而每个事务都应表现为独立执行。串行的执行一系列事务的效果应该同于并发的执行它们。这要求两件事: 在一个事务执行过程中,数据的中间的(可能不一致)状态不应该被暴露给所有的其他事务。 两个并发的事务应该不能操作同一项数据。数据库管理系统通常使用锁来实现这个特征。 持久性(DURABILITY): 一个被完成的事务的效果应该是持久的。 说的狭隘一点:就是你做你的事,我做我的事,但对事务的基本特征却没什么改变。比如说是一工具箱,我借钳子,你也借钳子,但我时间上比你早那么一点点,我用完了再给你,给你的还是一钳子,而不是钣手,而且你用的时候,东西也没坏。公共的东西就是要保护好,大家都要用的。 这里我就说说要常用的spring的事务管理。  spring 有声明式,也有编码式的。编码的开发我是很少用就说说声明的吧。这个要用到一个概念叫AOP(Aspect Oriented Programming).说白了就是在你的程序外面包层东西,让他符合这个事务的特性。

Spring也提供声明式事务管理。这是通过AOP实现的。大多数Spring用户选择声明式事务管理,这是最少影响应用代码的选择,因而这是和非侵入性的轻量级容器的观念是一致的。

1)通常通过TransactionProxyFactoryBean设置Spring事务代理。需要一个目标对象包装在事务代理中。这个目标对象一般是一个普通Javabean。当我们定义TransactionProxyFactoryBean时,必须提供一个相关的PlatformTransactionManager的引用和事务属性。事务属性含有事务定义。例如:

 

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

这玩艺就是相关的 PlatformTransactionManager的引用和事务属性。

 

然后主体到了:

 

  1. <bean id="transactionService"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 
  2. <property name="transactionManager"> 
  3. <ref   local="transactionManager"/> 
  4. </property> 
  5. <property  name="target"> 
  6. <ref  local="transactionServiceControl"/> 
  7. </property> 
  8. <property  name="transactionAttributes"> 
  9. <props> 
  10. <prop key=”insert*”>PROPAGATION_REQUIRED,-MyCheckedException</prop> 
  11. <prop key=”update*”>PROPAGATION_REQUIRED</prop> 
  12. <prop key=”*”>PROPAGATION_REQUIRED,readOnly</prop> 
  13. </props> 
  14. </property> 
  15. </bean>

 

事务代理会实现目标对象的接口:这里是属性名是target的引用。id是transactionServiceControl。(使用CGLIB也可以实现具体类的代理。只要设置proxyTargetClass属性为true即可。如果目标对象没有实现任何接口,这将自动设置该属性为true。通常,我们希望面向接口编程。)使用proxyInterfaces属性来限定事务代理来代理指定接口也是可以。也可以通过从org.springframework.aop.framework.ProxyConfig继承或所有AOP代理工厂共享的属性来定制TransactionProxyFactoryBean行为。

然后,说说属性名是transactionAttributes意义:
这里的transactionAttributes属性是定义在org.springframework.transaction.interceptor.NameMathTransactionAttributeSource中的属性格式设置。这个包括通配符的方法名称映射是很直观的,如”insert*”。注意insert*的映射的值包括回滚规则。”-MyCheckException”指定如果方法抛出MyCheckException或它的子类,事务会自动回滚。可以用逗号分隔多个回滚规则。“-”前缀强制回滚,“+”前缀指定提交(这允许即使抛出unchecked异常时也可以提交事务)。“PROPAGATION_REQUIRED”指定事务传播范围。

TransactionProxyFactoryBean允许你通过“preInterceptors”和“postInterceptors”属性设置前或后的拦截操作。可以设置任意数量的前和后通过,它们的类型可以是Advistor(切入点),MethodInterceptor或被当前Spring配置支持的通知类型。例如:ThrowAdvice,AfterReturningAdvice或BeforeAdvice。这些通知必须支持实例共享模式。如果你需要高级AOP特性操作事务,通过org.springframework.aop.framework.ProxyFactoryBean,而不是TransactionProxyFactory实用代理创建者。

-----------------------------------------------------------------------------------------

这个是简单的,对每一个逻辑,也就是代码中的action来进行处理。这样做的话,可能最后变成配置地狱,此时可以考虑使用自动事务代理。根据spring的BeanName来管理自动代理可以这样做:<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"><beans><bean id="dataSource"class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property><property name="url"><value>jdbc:mysql://localhost:3306/myuser</value></property><property name="username"><value>lighter</value></property><property name="password"><value>12345</value></property></bean><bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop><prop key="hibernate.show_sql">true</prop></props></property><property name="mappingResources"><list><value>org/mmc/dao/domain/User.hbm.xml</value></list></property></bean><!-- 配置Hibernate的事务管理器 --><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory" /></bean><!-- 定义事务拦截器bean --><bean id="transactionInterceptor"class="org.springframework.transaction.interceptor.TransactionInterceptor"><property name="transactionManager" ref="transactionManager" /><property name="transactionAttributes"><props><prop key="insert*">PROPAGATION_REQUIRED</prop><prop key="find*">PROPAGATION_REQUIRED,readOnly</prop><prop key="*">PROPAGATION_REQUIRED</prop></props></property></bean><!-- 定义BeanNameAutoProxyCreator--><beanclass="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"><property name="beanNames"><!-- 所有名字以DAO,Service结尾的bean,将由该"bean后处理器"为其创建事务代理;实际上应该在业务层进行事务管理,这里只是举一个简单例子 --><value>*DAO,*Service</value></property><!--  下面定义BeanNameAutoProxyCreator所需的事务拦截器--><property name="interceptorNames"><list><!-- 可以增加其他的拦截器 --><value>transactionInterceptor</value></list></property></bean><!-- 举下面这一个例子:这时候,这一个bean已经有了事务管理,可以增加类似的bean --><bean id="searchUserDAO" class="org.mmc.dao.impl.SearchUserDAO"><property name="sessionFactory" ref="sessionFactory" /></bean></beans>-----------------------------------------------------下面再看一种也是常用的使用bean继承简化事务代理配置<bean id="test1" class="test.TransactionTestImpl"><property name="ds"><ref local="dataSource"/></property></bean><bean id="test2" class="test.TestImpl"><property name="ds"><ref local="dataSource"/></property></bean>    <bean id="baseTxProxy" lazy-init="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">         <property name="transactionManager"><ref bean="transactionManager"/></property>         <property name="transactionAttributes">             <props>                 <prop key="*">PROPAGATION_REQUIRED</prop>             </props>         </property>     </bean>     <bean id="testTrans1" parent="baseTxProxy">         <property name="target">             <ref local="test1"/>         </property>     </bean>     <bean id="testTrans2" parent="baseTxProxy">         <property name="target">             <ref local="test2"/>         </property>     </bean> 使用继承的方法,其配置文件是增量式的,不如采用上面所说的第一种方法简捷,精炼。ok 就这么多,不知道说明白没有。呵呵
http://www.douban.com/note/433877038/
原创粉丝点击