事物管理:这个有点抽象,书面表达是这样的:
为了完成对数据的操作,企业应用经常要求并发访问在多个构件之间共享的数据。这些应用在下列条件下应该维护数据的完整性(由应用的商务规则来定义): 分布式访问一个单独的数据资源,以及从一个单独的应用构件访问分布式资源。 在这种情况,可能要求在(分布式)资源上的一组操作被当作一个工作单元(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的引用和事务属性。
然后主体到了:
- <bean id="transactionService"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
- <property name="transactionManager">
- <ref local="transactionManager"/>
- </property>
- <property name="target">
- <ref local="transactionServiceControl"/>
- </property>
- <property name="transactionAttributes">
- <props>
- <prop key=”insert*”>PROPAGATION_REQUIRED,-MyCheckedException</prop>
- <prop key=”update*”>PROPAGATION_REQUIRED</prop>
- <prop key=”*”>PROPAGATION_REQUIRED,readOnly</prop>
- </props>
- </property>
- </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--> <bean class="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/