天天看点

Spring框架事务管理之四:Spring编程式事务

虽然Spring框架推荐使用声明式事务管理,但是我们也要了解一下Spring的编程式事务。

Spring编程式事务仅适用于操作简单的事务,有两种编程实现的方式:

  • 直接使用org.springframework.transaction.PlatformTransactionManager接口的某个实现类

类似于直接使用JTA的事务API

  • 使用org.springframework.transaction.support.TransactionTemplate类(推荐方式)

TransactionTemplate类是org.springframework.transaction.TransactionDefinition接口的实现。

                TransactionTemplate是线程安全的,即其不维持事务运行的状态。但是TransactionTemplate维持着配置参数,可以作用于不同的事务中。

1.使用org.springframework.transaction.support.TransactionTemplate类实现Spring的编程式事务

1) 基本的代码如下所示:

public class SimpleService implements Service {

    // single TransactionTemplate shared amongst all methods in this instance
    private final TransactionTemplate transactionTemplate;

    // use constructor-injection to supply the PlatformTransactionManager
    public SimpleService(PlatformTransactionManager transactionManager) {
        Assert.notNull(transactionManager, "The ''transactionManager'' argument must not be null.");
        this.transactionTemplate = new TransactionTemplate(transactionManager);
    }

    public Object someServiceMethod() {
        return transactionTemplate.execute(new TransactionCallback() {
            // the code in this method executes in a transactional context
            public Object doInTransaction(TransactionStatus status) {
                try {
                    updateOperation1();
                    return resultOfUpdateOperation2();
                } catch (SomeBusinessExeption ex) {
                    status.setRollbackOnly();
                }
            }
        });
    }
}
           

说明:

初始化TransactionTemplate实例时,需要传入PlatformTransactionManager作为参数。

事务的执行位于TransactionTemplate实例的execute()方法中。

在TransactionTemplate实例的execute()方法中,需要一个org.springframework.transaction.support.TransactionCallback接口的实例作为参数。TransactionCallback接口的实例往往通过匿名内部类的方式给出,在匿名内部类中重写其doInTransaction()方法。

doInTransaction()方法会返回一个对象,作为事务执行的结果。所以,直接实现TransactionCallback接口适合于有返回结果的事务。

事务执行的过程中,如果发生异常,可以调用TransactionStatus的setRollbackOnly()方法回滚事务。

2) 对于事务的执行没有返回结果的情况,可以重写org.springframework.transaction.support.TransactionCallbackWithoutResult抽象类,并重写其doInTransactionWithoutResult()方法,如下:

public class SimpleService implements Service {

    private final TransactionTemplate transactionTemplate;

    public SimpleService(PlatformTransactionManager transactionManager) {
        Assert.notNull(transactionManager, "The ''transactionManager'' argument must not be null.");
        this.transactionTemplate = new TransactionTemplate(transactionManager);
    }

    public Object someServiceMethod() {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            public void doInTransaction<span style="font-family: Arial, Helvetica, sans-serif;">WithoutResult</span><span style="font-family: Arial, Helvetica, sans-serif;">(TransactionStatus status) {</span>
                try {
                    updateOperation1();
                    UpdateOperation2();
                } catch (SomeBusinessExeption ex) {
                    status.setRollbackOnly();
                }
            }
        });
    }
}
           

3) 上述示例中的TransactionTemplate实例采用默认的事务配置参数,还可以对TransactionTemplate实例设置参数,如下所示:

public class SimpleService implements Service {

    private final TransactionTemplate transactionTemplate;

    public SimpleService(PlatformTransactionManager transactionManager) {
        Assert.notNull(transactionManager, "The ''transactionManager'' argument must not be null.");
        this.transactionTemplate = new TransactionTemplate(transactionManager);

        // the transaction settings can be set here explicitly if so desired
        this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
        this.transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        this.transactionTemplate.setReadOnly(true); 
        this.transactionTemplate.setTimeout(30); // 30 seconds
        // and so forth...
    }
}
           

4) 大家可能已经注意到了,TransactionTemplate实例完全可以通过Spring Bean的方式注入,其在XML配置文件中的配置示例如下:

<bean id="sharedTransactionTemplate"
        class="org.springframework.transaction.support.TransactionTemplate">
    <property name="isolationLevelName" value="ISOLATION_READ_UNCOMMITTED"/>
    <property name="propagationBehavior" value="PROPAGATION_REQUIRED"/>
    <property name="readOnly" value="true"/>
    <property name="timeout" value="30"/>
</bean>"
           

2.使用org.springframework.transaction.PlatformTransactionManager接口的实现类实现Spring的编程式事务

在代码中首先实例化PlatformTransactionManager接口的一个实现类,也可以通过Spring Bean的方式注入。

然后就可以通过PlatformTransactionManager实例的getTransaction()方法得到TransactionStatus的实例,并进而进行事务操作,示例如下:

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
// explicitly setting the transaction name is something that can only be done programmatically
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatus status = txManager.getTransaction(def);
try {
    // execute your business logic here
}
catch (MyException ex) {
    txManager.rollback(status);
    throw ex;
}
txManager.commit(status);
           

说明,设置PlatformTransactionManager实例的事务参数用到了DefaultTransactionDefinition实例。

PlatformTransactionManager实例的注入可以参考本系列博文。