1、传统事务控制存在的问题:
持久化技术不同,事务控制的API也会不同,会导致事务控制代码也会随之改变。程序将Service层与DAO分离,目的就是为让Service只负责业务变化,DAO专门负责持久化技术的变化。事务控制代码需要放在Service层完成,持久化技术的改变,必然导致Service组件也要随之修改。
2、Spring的事务控制
(1)特征:Spring的事务管理不需要与任何特定的事务API耦合(面向PlatformTransactionManager)。对不同的持久层访问技术,编程式事务提供一致的事务管理,通过模块化的一致性操作管理事务。
(2)优势:
①不需要硬编码的方式写事务
②让业务逻辑API与具体的事务逻辑分离
③没有提供实际的事务支持,只是对底层的事务包装,所以能自由切换底层的事务
(3)事务控制中的策略模式:当程序要完成某个功能时(事务),但实现该功能可能有多个实现算法,目前不希望或不确定要采用哪种实现算法,此时可考虑使用策略模式。
策略模式由如下部分组成:
① 一个策略接口,该策略接口只定义实现功能所需的方法,不提供实现。
PlatformTransactionManager:事务控制的策略接口。只定义事务控制的3个方法。
②N个策略实现类:为不同的算法提供对应的策略实现类。
DataSourceTransactionManager:采用JDBC持久化技术,用该事务策略实现类。
HibernateTransactionManager:采用Hibernate持久化技术,用该事务策略实现类。
JpaTransactionManager:采用JPA持久化技术,用该事务策略实现类。
JtaTransactionManager:使用JTA全局事务,用该事务策略实现类
WebLogicJtaTransactionManager, WebSphereUowTransactionManager
③Context类:负责为程序“智能”地选择一个策略实现类。 ——其实要靠配置。
ApplicationContext
TransactionDefinition:代表事务定义。用于指定事务相关属性。(隔离级别、传播性、超时、是否只读)
(4)Spring的事务控制有两种方式:
①编程式事务。需要自己来写Java代码控制事务。面向PlatformTransactionManager编程、还可结合AOP。
a.增加aspect类
public class TxAspect {
private PlatformTransactionManager transactionManager;
public void setTransactionManager(PlatformTransactionManager transactionManager)
{
this.transactionManager = transactionManager;
}
// 定义一个Around Advice
public Object tx(ProceedingJoinPoint jp){
// 创建默认的事务定义(永不超时) ——是不好的。
DefaultTransactionDefinition td = new DefaultTransactionDefinition();
// 开启事务, 需要传入TransactionDefinition对象,用于指定事务相关的属性(隔离、传播、超时、只读)
TransactionStatus status = transactionManager.getTransaction(td);
Object rvt = null;
try {
rvt = jp.proceed(); // 直接使用原来的参数调用目标方法
transactionManager.commit(status);// 提交事务
} catch (Throwable e) {
e.printStackTrace();
transactionManager.rollback(status);// 回滚事务
}
return rvt;
}
}
b.在appCtx中配置:
<!-- 此处就是配置事务策略的实现类,也就是为PlatformTransactionManager指定实现类 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
<bean id="txAspect" class="aspect.TxAspect"
p:transactionManager-ref = "transactionManager"
/>
<aop:config>
<aop:pointcut expression="execution(* service.impl.*.*(..))"
id="pc" />
<!-- 将txAspect当成Aspect使用 -->
<aop:aspect ref="txAspect">
<aop:around method="tx" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
②声明式事务。不需要自己写Java代码,只要用XML或注解配置即可。
a.在appCtx中配置:
注意:需要导入tx命名空间
<!-- 以下为事务配置 -->
<!-- 为PlatformTransactionManager事务策略接口指定实现类,
ApplicationContext就会为我们选择该事务策略实现类
-->
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory"/>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 下面就是用于定义事务属性 -->
<tx:attributes>
<!-- 访问get方法属性配置 -->
<tx:method name="get*" read-only="true" timeout="8"/>
<!-- 访问其他方法属性配置 -->
<tx:method name="*" timeout="5"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!-- 为切入点表达式起个名字 -->
<aop:pointcut expression="execution(* service.impl.*.*(..))"
id="pc" />
<!-- 指定将指定的Advice,织入到切入点表达式所匹配的方法。 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pc" />
</aop:config>
其余代码可参考: Spring3.3节中s2sh整合
3、注解配置事务可参考:Spring 使用注解方式进行事务管理