1. 程式人生 > >Spring框架事務管理之四:Spring程式設計式事務

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例項的注入可以參考本系列博文。