事务的编程模型

在上一篇文章里面写了关于事务的一些特性,这里在谈谈事务的编程模型。什么叫做事务的编程模型,这个问题比较难以回答,其实简单的一句话,就是我们如何去使用和控制事务。在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提供的编程模型即可。