1. 程式人生 > >Spring註解方式管理事務以及事務傳播行為Propagation

Spring註解方式管理事務以及事務傳播行為Propagation

使用@Transactional註解宣告Bean底下所有業務方法需要事務管理。
1.預設一個業務方法開啟和結束事務,什麼時候提交,什麼時候回滾呢?
Spring容器預設情況下對於執行期異常(unchecked Exception)會進行事務回滾,如果是使用者違例(checked Exception),事務不會回滾。
執行期違例:throw new RuntimeException("XXX");執行期違例不需要使用try/catch捕捉,編譯可以通過
使用者違例,throw new Exception("XXX");必須使用try/catch捕捉,否則編譯不能通過。
也可以修改這種行為,在業務方法上加上@Transactional(rollbackFor=Exception.class),則cheked Exception也會回滾。
如果@Transactional(noRollbackFor=RuntimeException.class),則執行期例外也不會回滾。
2.有些業務方法不需要業務管理,如獲取資料的。開啟事務會對效能有影響。所以使用
@Transactional(propagation=Propagation.NOT_SUPPORTED)
propagation屬性指定事務的傳播行為。則Spring容器在該業務方法前不會開啟事務。
事務的傳播屬性:
(1)Propagation.REQUIRED,表示業務方法需要在一個事務中執行,如果方法執行時已經在一個事務中,則加入到該事務,否則建立一個新事務。預設為這種。
(2)Propagation.NOT_SUPPORTE。如果該方法沒有關聯事務,容器不會為該方法開啟事務。注意如果這個Bean方法不需要事務,但它被另一個開啟事務的業務方法呼叫(它在一個事務中被呼叫),那麼該事務會被掛起,執行結束後事務恢復執行。
(3)Propagation.REQUIRES_NEW。必須開啟一個新的事務,不管它是否在一個事務中。如果該方法被另一個開啟事務的業務方法呼叫,則原有事務被掛起,新的事務建立,方法結束後新事務結束,原事務恢復執行。
(4)Propagation.MANDATORY 指定該業務方法只能在一個已有的事務中執行,業務方法本身不能發起事務,假設它沒有在事務中執行,則Spring丟擲異常。
(5)Propagation.SUPPORTS 如果該方法在某個事務範圍內被呼叫,則它成為事務的一部分。如果在一個沒有事務的範圍內被呼叫,則它
(6)Propagation.NEVER 要求不能在一個事務中執行,如果它在一個事務環境中被呼叫,則容器丟擲例外。
以上幾種是EJB裡的事務屬性,Spring增加了一個:
(7)Propagation.NESTED 如果一個活動的事務存在,則執行在巢狀的事務中,如果沒有活動事務,則會按REQUIRED來。它使用一個單獨的事務。事務擁有多個可以回滾的儲存點,內部事務的回滾不會影響外部。只適用於DataSourceTransactionManager。
Spring的工作類似下面:
(以下內容來自:http://blog.csdn.net/xiaolang8762400/article/details/5693658)
在執行操作前,新建一個儲存點

//執行update方法時,判斷它的事務屬性是NESTED,它會先做一個儲存點
Savepoint savepoint = conn.setSavepoint();
try{
conn.createStatement().executeUpdate("update person set name='222' where sid=2");
}catch(Exception ex){
conn.rollback(savepoint);
//當在執行語句時出現問題,這時候會回滾,回滾到儲存點
}

@Transactional中其它屬性:
readOnly:代表只讀,可通過這個設成只讀事務,對於只讀事務,它就不能進行更新操作,這樣能提高效率的。
timeout:代表事務的超時時間,
isolation:資料庫的隔離級別,這個實際上並不是由Spring容器實現的,這個主要是依賴於底層資料庫來實現的。

---------------------------------------------------------------------------
資料庫系統提供了四種事務隔離級別供使用者選擇。[b]不同的隔離級別採用不同的鎖型別(共享鎖,更新鎖,排他鎖)[/b]來實現,在Serializable的隔離級別最高。大多資料庫預設的隔離級別為Read Commited,如SqlServer,當然也有少部分資料庫預設的隔離級別為Repeatable Read ,如Mysql
Read Uncommited:讀未提交資料(會出現髒讀,不可重複讀和幻讀)。
Read Commited:讀已提交資料(會出現不可重複讀和幻讀)
Repeatable Read:可重複讀(會出現幻讀)
Serializable:序列化

髒讀:一個事務讀取到另一事務未提交的更新新據。
不可重複讀:在同一事務中,多次讀取同一資料返回的結果有所不同。換句話說就是,後續讀取可以讀到另一事務已提交的更新資料。相反,“可重複讀”在同一事務中多次讀取資料時,能夠保證所讀資料一樣,也就是,後續讀取不能讀到另一事務已提交的更新資料。
幻讀:一個事務讀取到另一事務已提交的insert資料。