容器管理事務(Container-Managed
Transaction, CMT
):容器管理事務允許組件自動征集(enlist
)到事務中,也就是說,EJB
組件從不需要顯式地給出begin
、commit
、abort
語句,EJB
容器會替開發者考慮這些內容。EJB
容器會依據EJB
組件提供者指定的事務行為來界定相應的事務邊界。在使用容器管理事務時,EJB
容器會攔截客戶請求,并自動為EJB
組建啟動新的事務,也就是說,容器會通過begin
語句調用底層事務系統,從而啟動事務。隨后,容器會將業務請求委派給EJB
組件,組件中的業務操作將運行在這一事務中。處于事務中的EJB
組件能夠執行任何業務邏輯,如寫入數據庫、發送異步信息、調用其他的EJB
組件等。一旦在處理業務過程中出現問題,則EJB
組建需要通知EJB
容器去回滾事務。當EJB
組建完成業務處理后,會將控制權交回給EJB
容器。隨后,EJB
容器能夠通過commit
或abort
語句調用底層事務系統。
通過使用@TransactionAttribute
注釋或部署描述符,開發者能夠指定事務屬性。EJB
容器通過分析事務屬性便能夠知道如何處理EJB
組件的事務需求。EJB
事務屬性的取值有:
(1
)Required
,如果EJB
組件必須總是運行在事務中,則應該使用Required
模式。如果已經有事務在運行,則EJB
組件參與其中;如果沒有事務運行,則EJB
容器會為EJB
組件啟動新的事務。
Required
是默認和最常使用的事務屬性值。這個值指定必須在事務之內調用EJB
方法。如果從非事務性客戶端調用方法,那么容器會在調用方法之前開始事務,并且在方法返回時結束事務。另一方面,如果調用者從事務性上下文調用方法,那么
方法會聯結已有事務。在從客戶段傳播事務的情況下,如果我們的方法表示應該回滾事務,那么容器不僅回回滾整個事務,而且會向客戶端拋出異常,從而讓客戶端
知道它開始的事務已經被另一個方法回滾了。
(2
)Requires_New
,當客戶調用EJB
時,如果總是希望啟動新的事務,則應該使用RequiresNew
事務屬性,如果客戶在調用EJB
組件時已經存在事務,則當前事務會被掛起,進而容器啟動新的事務,并將調用請求委派給EJB
組件。也就是說,如果客戶端已經有了事務,那么它暫停該事務,知道方法返回位置,新事務是成功還是失敗都不會影響客戶端已有的事務。EJB
組件執行相應的業務操作,容器會提交或回滾事務,最終容器將恢復原有的事務,當然,如果客戶在調用EJB
組件時不存在事務,則不需要執行事務的掛起或恢復操作。
RequiresNew
事務屬性非常有用。如果EJB
組件需要事務的ACID
屬性,并且將EJB
組件運行在單個獨立的工作單元中,從而不會將其他外部邏輯也包括在當前的事務中,則必須使用RequiredNew事
務屬性。如果需要事務,但是不希望事務的回滾影響客戶端,就應該使用它。另外,當不希望客戶端的回滾影響你的時候,也應該使用這個值。日志記錄是個很好的
例子,即使父事務回滾,你也希望把錯誤情況記錄到日志中,另一方面,日志記錄細小調試信息的失敗不應該導致回滾整個事務,并且問題應該僅限于日志記錄組件
內。
(3
)Supports
,如果某個EJB
組件使用了Supports
事務屬性,則只有調用它的客戶已經啟用了事務時,這一EJB
組件才會運行在事務中。如果客戶并沒有運行在事務中,則EJB
組建也不會運行在事務中。Supports
同Required
事務屬性很相似,但是,Required
要求EJB
組件必須運行在事務中。如果使用Support
事務屬性,EJB
組建很可嫩沒有運行在事務中。
(4
)Mandatory
,Mandatory
事務屬性要求調用EJB
組件的客戶必須已經運行在事務中。如果從非事務性客戶端調用使用Mandatory
屬性的EJB
方法,那么客戶將接受到系統拋出的javax.ejb.EJBTransactionRequiredException
異常。EJB
組件使用Mandatory
事務屬性是非常安全的,它能夠保證EJB
組建運行在事務中。如果客戶沒有運行在事務中,則不能夠調用到應用了Mandatory
事務屬性的EJB
組件。但是,Mandatory
事務屬性要求第3
方(及客戶)在調用EJB
組件前必須啟動了事務。EJB
容器并不會為Mandatory
事務屬性自動啟動新事務,這是同Support
事務屬性的最主要區別。
(5
)NotSupported
,如果EJB
組件使用了NotSupport
事務屬性,它根本不會參與到事務中。如果調用者使用相關聯的事務調用方法,容器就會暫停事務,調用方法,然后再方法返回時恢復事務。通常,此屬性只用于非實物性的自動確認模式中,支持JMS
提供者的MDB
。
(6
)Never
,如果EJB
組件使用Never
事務屬性,它就不能夠參與到事務中,而且,如果調用它的客戶已經處于事務中,則容器會將javax.ejb.EJBException
異常拋給客戶。
事務效果圖,其中,T1
和T2
是2
個不同的事務,T1
是客戶請求傳遞的事務,T2
是容器啟動的事務,通過下表,能夠理解各種事務屬性在影響事務長度和范圍方面所起的重要作用。
事務屬性
|
客戶事務
|
EJB
組件事務
|
Required
|
無
T1
|
T2
T1
|
RequiresNew
|
無
T1
|
T2
T2
|
Supports
|
無
T1
|
無
T1
|
Mandatory
|
無
T1
|
錯誤
T1
|
NotSupported
|
無
T1
|
無
無
|
Never
|
無
T1
|
無
錯誤
|