Spring框架事務管理之四:Spring程式設計式事務
雖然Spring框架推薦使用宣告式事務管理,但是我們也要了解一下Spring的程式設計式事務。
Spring程式設計式事務僅適用於操作簡單的事務,有兩種程式設計實現的方式:
- 直接使用org.springframework.transaction.PlatformTransactionManager介面的某個實現類
- 使用org.springframework.transaction.support.TransactionTemplate類(推薦方式)
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例項的注入可以參考本系列博文。