在上一篇文章里面写了关于事务的一些特性,这里在谈谈事务的编程模型。什么叫做事务的编程模型,这个问题比较难以回答,其实简单的一句话,就是我们如何去使用和控制事务。在java平台里面,有三种事务编程模型:本地事务模型,编程式事务模型,声明式事务模型(当然我不是太认同这种说法,并不是太准确,不过大体也就这么回事情)
-
本地事务模型
本地事务模型:不用事务的编程框架来管理事务,直接使用资源管理器来控制事务。典型的就是java.sql.Connection 中的 setAutoCommit、commit、rollback方法,见下面一段代码,直接使用资源管理器进行事务控制
Connection conn = getConnection();
conn.setAutoCommit(false);
// do something
boolean success = doSomething();
if (success) {
conn.commit();
} else {
conn.rollback();
}
-
编程式事务模型
编程式事务模型:就是使用java提供的事务api JTA(Java Transaction API)
和事务服务提供者(一般是指j2ee容器) 进行事务控制,JTA里面提供了 java.transaction.UserTransaction ,里面定义了下面几个方法
begin:开启一个事务
commit:提交当前事务
rollback:回滚当前事务
setRollbackOnly:把当前事务标记为回滚
setTransactionTimeout:设置事务的事件,超过这个事件,就抛出异常,回滚事务
getStatus;
不过JTA只是提供了一个接口,并没有提供具体的实现,而是由j2ee服务器提供商 根据JTS规范提供的。下面一段代码演示了如何使用事务JPA
InitialContext ctx = new InitialContext();
UserTransaction ut = (UserTransaction)
ctx.lookup("javax.transaction.UserTransaction");
ut.begin();
//do something
boolean isSuccess = doSomething() ;
if(isSuccess){
ut.commit();
}else{
ut.rollback();
}
JPA规范里面定义了事务相关的几个角色:事务上下文,资源管理器,通信管理器,应用程序,事务管理器,事务服务提供者。其中资源管理器主要就是我们常见的数据库连接和JMS连接,事务上下文这里可以理解为事务的状态和属性信息,应用程序就是使用事务服务的程序,事务服务提供者就是实现了jta规范的j2ee容器。事务管理器就是应用程序和事务服务提供者的api接口。通信管理器主要是用在分布式事务里面。
这个是java里面JPA的规范,但是也有一些编程框架提供了自己的编程事务模型,例如java里最常用的就是spring的事务管理器,下面是spring提供的编程接口:org.springframework.transaction.PlatformTransactionManager,这里面就只有三个方法:
getTransaction:根据属性信息决定是否开启事务(具体可以看上一篇文章里面的事务特性小结里面的事务传播属性)
commit;提交当前事务
rollback;回滚当前事务
我们发现其实和JPA提供的编程模型很像,就是开启一个事务,提交还是回滚事务。spring提供的事务编程框架也比较简单
ApplicationContext context = getApplicationContext();
TransactionTemplate transactionTemplate = (TransactionTemplate)context.getBean("TransactionTemplate");
transactionTemplate.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
boolean isSuccess = doSomething() ;
if(isSuccess){
}else{
status.setRollbackOnly();
}
return isSuccess;
}
});
-
声明式编程
声明式编程:这种编程模型不采用硬编码的方式,而是采用在xml里面进行配置的方式或者使用anotation的方式进行。例如srping里面可以通过aop进行实现
<bean id="accountService"
class="org.springframework.transaction.interceptor. TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref="accountServiceTarget"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_SUPPORTS</prop>
<prop key="update*">PROPAGATION_REQUIRED </prop>
</props>
</property>
以上三种编程模型,第一种比较简单,也只是适合控制单个资源事务,如果涉及到跨资源(比如两个数据库连接之间)事务控制,就无能为力了,也就是说不能够提供分布式事务的解决方案, 而JPA提供了分布式事务的解决方案,这一块以前了解过,后来忘记了,准备在温习一下,在整理和总结以下。而spring提供的编程事务模型,则是在局部事务和JPA事务的基础上提供了一层封装,统一了两者的编程模型,也就是说spring其实也提供JPA的编程接口,也就是 JtaTransactionManager,只不过具体实现 委托给jta provider而已。所以基本上编程模型这个划分还是比较模糊的,直接使用spring提供的编程模型即可。