Spring的编程式事务和声明式事务详解
|
入口(了解一些基本概念) Spring事务属性(事务的属性有哪些?) 我们都知道事务有开始,保存点,提交,回滚,隔离级别等属性。那么Spring对于事务属性定义有哪些呢?通过TransactionDefinition接口我们可以了解到:
public interface TransactionDefinition{
int getIsolationLevel();
int getPropagationBehavior();
int getTimeout();
boolean isReadOnly();
}
获取隔离级别 获取传播特性 获取超时 获取是否只读 事务隔离级别 隔离离别也是通过TransactionDefinition接口定义的,代表并发事务的隔离程度。
* 事务传播行为 所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量.
* 事务超时 指定事务的最大运行时间。使用int指定,单位是秒。 * 事务的只读属性 事务的只读属性是指,对事务性资源进行只读操作或者是读写操作。所谓事务性资源就是指那些被事务管理的资源,比如数据源、 JMS 资源,以及自定义的事务性资源等等。如果确定只对事务性资源进行只读操作,那么我们可以将事务标志为只读的,以提高事务处理的性能。在 TransactionDefinition 中以 boolean 类型来表示该事务是否只读。 * 事务的回滚规则 默认出现RuntimeException就会回滚。如果没有抛出任何异常,或者抛出了已检查异常,则仍然提交事务。这通常也是大多数开发者希望的处理方式,也是 EJB 中的默认处理方式。(这里个人理解的是已检查异常,是我们定义的checkedException,包括我们自定义的异常和调用方法捕获的异常) Spring事务的三个基本类 Spring 框架中,涉及到事务管理的 API 大约有100个左右,其中最重要的有三个:TransactionDefinition、PlatformTransactionManager、TransactionStatus。所谓事务管理,其实就是“按照给定的事务规则来执行提交或者回滚操作”。“给定的事务规则”就是用 TransactionDefinition 表示的,“按照……来执行提交或者回滚操作”便是用 PlatformTransactionManager 来表示,而 TransactionStatus 用于表示一个运行着的事务的状态。打一个不恰当的比喻,TransactionDefinition 与 TransactionStatus 的关系就像程序和进程的关系。 TransactionDefinition 定义事务的属性 TransactionStatus 定义事务的状态
public interface TransactionStatus{
boolean isNewTransaction();
void setRollbackOnly();
boolean isRollbackOnly();
}
PlatformTransactionManager 就是各种事务平台的实现接口
Public interface PlatformTransactionManager{
TransactionStatus getTransaction(TransactionDefinition definition)
throws TransactionException;
void commit(TransactionStatus status)throws TransactionException;
void rollback(TransactionStatus status)throws TransactionException;
}
所以我们现在可以向下,spring的事务真正实现是PlatformTransactionManager的实现类,通过各种参数来符合TransactionDefinition和TransactionStatus的要求,最后根据我们编程的或者声明的进行事务管理。 根据底层框架的不同(稍后我们看一下DataSourceTransactoinManager和HibernateTransactionManager的代码,主要做了什么),Spring(或者其他框架)提供主要的实现如下: DataSourceTransactionManager: 适合JDBC和ibatis HibernateTransactionManager: 适合hibernate JpaTransactionManager: 适用于使用JPA进行数据持久化操作的情况(更底层的一些) 适用于使用JPA进行数据持久化操作的情况 到这里基本概念终于结束了,我们可以介绍两种类型的事务管理了 编程式事务管理 首先我们回想一下不适用spring事务管理时,hibernate事务的管理是怎么样的? 大概是我们手动获取session,获取transaction,开始transaction,提交或者回滚,关闭session 那么我们使用spring的管理之后,事务本身控制还是交给持久框架自己管理。知识spring像一个代理人一样,你告诉它,它之后转化后告诉底层框架。 看个实际例子吧: 基于底层API的编程式事务管理
public class BankServiceImpl implements BankService {
private BankDao bankDao;
private TransactionDefinition txDefinition; // transaction定义是哪个
private PlatformTransactionManager txManager; //具体使用的txmanager
......
public boolean transfer(Long fromId, Long toId, double amount) {
//这里获取事务状态
TransactionStatus txStatus = txManager.getTransaction(txDefinition);
boolean result = false;
try {
result = bankDao.transfer(fromId, toId, amount);
//提交事务
txManager.commit(txStatus);
} catch (Exception e) {
result = false;
//回滚
txManager.rollback(txStatus);
System.out.println("Transfer Error!");
}
return result;
}
}
对应的xml文件:
<bean id="bankService" class="footmark.spring.core.tx.programmatic.origin.BankServiceImpl">
<property name="bankDao" ref="bankDao"/>
<property name="txManager" ref="transactionManager"/>
<property name="txDefinition">
<bean class="org.springframework.transaction.support.DefaultTransactionDefinition">
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
</bean>
</property>
</bean>
但是这种写法和我们不适用spring的有何不同呢,最多是将事务层次提高了service层,不限于dao层,所以Spring做了改进: TransactionTemplate的execute方法提供一个内部匿名类,用来我们写transaction代码,然后提供一个transactionStatus的参数,这样你可以控制回滚。这样一来,我们就不用写任何关于事务API的代码了。格式大概是 Boolean b = transactionTempate.execute(new TransactionCallBack() { 执行方法(TransactionStatus transactionStatus){} },当执行完成后返回一个boolean的值. 还有一个方法,就是不提供返回结果的。
public class BankServiceImpl implements BankService {
private BankDao bankDao;
private TransactionTemplate transactionTemplate;
......
public boolean transfer(final Long fromId, final Long toId, final double amount) {
//调用一个回调函数
return (Boolean) transactionTemplate.execute(new TransactionCallback(){
public Object doInTransaction(TransactionStatus status) {
Object result;
try {
result = bankDao.transfer(fromId, toId, amount);
} catch (Exception e) {
status.setRollbackOnly();
result = false;
System.out.println("Transfer Error!");
}
return result;
}
});
}
}
对应的XML: <bean id="bankService" class="footmark.spring.core.tx.programmatic.template.BankServiceImpl"> <property name="bankDao" ref="bankDao"/> <property name="transactionTemplate" ref="transactionTemplate"/> </bean> 从结果来看,好像还是不够简单和清晰。下面我们来看声明式事务管理,也是比较推荐的方式 声明式事务管理 Spring的声明式事务管理是基于AOP的,在方法前和后加上切点,用来打开事务和提交/回滚事务。 基于TransactionInterceptor的管理 最初,Spring 提供了 TransactionInterceptor 类来实施声明式事务管理功能
<beans...>
......
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
//指定了方法,可以使用通配符
<prop key="transfer">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="bankServiceTarget"
class="footmark.spring.core.tx.declare.origin.BankServiceImpl">
<property name="bankDao" ref="bankDao"/>
</bean>
<bean id="bankService"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="bankServiceTarget"/>
<property name="interceptorNames">
<list>
<idref bean="transactionInterceptor"/>
</list>
</property>
</bean>
......
</beans>
首先,我们配置了一个 TransactionInterceptor 来定义相关的事务规则,他有两个主要的属性:一个是 transactionManager,用来指定一个事务管理器,并将具体事务相关的操作委托给它;另一个是 Properties 类型的 transactionAttributes 属性,它主要用来定义事务规则,该属性的每一个键值对中,键指定的是方法名,方法名可以使用通配符,而值就表示相应方法的所应用的事务属性。 指定事务属性的取值有较复杂的规则,这在 Spring 中算得上是一件让人头疼的事。具体的书写规则如下: 传播行为 [,隔离级别] [,只读属性] [,超时属性] [不影响提交的异常] [,导致回滚的异常] 基于 TransactionProxy… 的声明式事务管理 前面的声明式事务虽然好,但是却存在一个非常恼人的问题:配置文件太多。 (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- java – 未调用RecyclerView Adapter方法
- Java 8 Function函数式接口及函数式接口实例
- java – maven-assembly-plugin MojoExecutionException,其
- java – SWT浏览器专注于下一个和上一个高亮文本
- 如何在使用Axis 1.4 wsdl2java生成的客户端时获取SOAP消息
- java – Hibernate在关系中创建错误的实体子类型
- java导出Excel通用方法的实例详解
- java – 使用Eclipse创建Scala项目,sbteclipse – 目录布局
- java – JasperReport报告中的Excel单元格格式
- java – 使用Apache Spark将RDD写为文本文件
