?
This document uses PHP Chinese website manual Release
Spring提供兩種方式的編程式事務(wù)管理:
使用 TransactionTemplate
直接使用一個(gè) PlatformTransactionManager
實(shí)現(xiàn)
如果你選擇編程式事務(wù)管理,Spring小組推薦使用 TransactionTemplate
。
第二種方法則類似使用JTA的 UserTransaction
API (除了異常處理的部分稍微簡(jiǎn)單點(diǎn))。
TransactionTemplate
采用與Spring中別的 模板 同樣的方法,
如 JdbcTemplate
。它使用回調(diào)機(jī)制,將應(yīng)用代碼從樣板式的資源獲取和釋放代碼中解放出來(lái),
這樣寫出的代碼是目的驅(qū)動(dòng)的,把精力集中在開發(fā)者想要做的事情上。
就像你馬上要在后面的例子中看到的那樣,
使用 TransactionTemplate
絕對(duì)會(huì)增加你的代碼與Spring的事務(wù)框架和API間的耦合。
到底編程式事務(wù)管理是不是適合你的項(xiàng)目需要由你自己來(lái)決定。
應(yīng)用的代碼必須在一個(gè)事務(wù)性的上下文中執(zhí)行,這樣就會(huì)像這樣一樣顯式的使用TransactionTemplate
。你作為一個(gè)應(yīng)用程序員,
會(huì)寫一個(gè) TransactionCallback
的實(shí)現(xiàn),
(通常會(huì)用匿名類來(lái)實(shí)現(xiàn) )這樣的實(shí)現(xiàn)會(huì)包含所以你需要在該事務(wù)上下文中執(zhí)行的代碼。
然后你會(huì)把一個(gè)你自己實(shí)現(xiàn)TransactionCallback
的實(shí)例傳遞給TransactionTemplate
暴露的execute(..)
方法。
public class SimpleService implements Service { // singleTransactionTemplate
shared amongst all methods in this instance private final TransactionTemplate transactionTemplate; // use constructor-injection to supply thePlatformTransactionManager
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) { updateOperation1(); return resultOfUpdateOperation2(); } }); } }
如果不需要返回值,更方便的方式是創(chuàng)建一個(gè) TransactionCallbackWithoutResult
的匿名類,如下:
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
updateOperation1();
updateOperation2();
}
});
回調(diào)方法內(nèi)的代碼可以通過(guò)調(diào)用 TransactionStatus
對(duì)象的 setRollbackOnly()
方法來(lái)回滾事務(wù)。
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
updateOperation1();
updateOperation2();
} catch (SomeBusinessExeption ex) {
status.setRollbackOnly();
}
}
});
諸如傳播模式、隔離等級(jí)、超時(shí)等等的事務(wù)設(shè)置都可以在TransactionTemplate
中或者通過(guò)配置或者編程式地實(shí)現(xiàn)。
TransactionTemplate
實(shí)例默認(rèn)繼承了默認(rèn)事務(wù)設(shè)置。
下面有個(gè)編程式的為一個(gè)特定的TransactionTemplate
定制事務(wù)設(shè)置的例子。
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.setTimeout(30); // 30 seconds // and so forth... } }
在下面的例子中,我們將會(huì)演示如何使用Spring XML配置來(lái)定制TransactionTemplate
的事務(wù)屬性。
'sharedTransactionTemplate
'可以被注入到所有需要的服務(wù)中去。
<bean id="sharedTransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="isolationLevelName" value="ISOLATION_READ_UNCOMMITTED"/> <property name="timeout" value="30"/> </bean>"
最后,TransactionTemplate
類的實(shí)例是線程安全的,任何狀態(tài)都不會(huì)被保存。
TransactionTemplate
實(shí)例 的確會(huì)
維護(hù)配置狀態(tài),所以當(dāng)一些類選擇共享一個(gè)單獨(dú)的 TransactionTemplate
實(shí)例時(shí),
如果一個(gè)類需要使用不同配置的TransactionTemplate
(比如,不同的隔離等級(jí)),
那就需要?jiǎng)?chuàng)建和使用兩個(gè)不同的TransactionTemplate
。
你也可以使用 org.springframework.transaction.PlatformTransactionManager
來(lái)直接管理你的事務(wù)。只需通過(guò)bean的引用,簡(jiǎn)單的把你在使用的PlatformTransactionManager
傳遞給你的bean。
然后,使用TransactionDefinition
和TransactionStatus
對(duì)象,
你可以啟動(dòng),回滾和提交事務(wù)。
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);