情況1:如果沒有在程序中手動捕獲異常
@Transactional(rollbackFor = { Exception.class })
public void test() throws Exception {
doDbStuff1();
doDbStuff2();//假如這個操作數(shù)據(jù)庫的方法會拋出異常冕茅,現(xiàn)在方法doDbStuff1()對數(shù)據(jù)庫的操作 會回滾伤极。
}
情況2:如果在程序中自己捕獲了異常
@Transactional(rollbackFor = { Exception.class })
public void test() {
try {
doDbStuff1();
doDbStuff2();//假如這個操作數(shù)據(jù)庫的方法會拋出異常,現(xiàn)在方法doDbStuff1()對數(shù)據(jù)庫的操作 不會回滾姨伤。
} catch (Exception e) {
e.printStackTrace();
}
}
現(xiàn)在如果我們需要手動捕獲異常哨坪,并且也希望拋異常的時候能回滾腫么辦呢?
下面這樣寫就好了乍楚,手動回滾事務:
@Transactional(rollbackFor = { Exception.class })
public void test() {
try {
doDbStuff1();
doDbStuff2();
} catch (Exception e) {
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//就是這一句了齿税,加上之后,如果doDbStuff2()拋了異常, doDbStuff1()是會回滾的
}
}
事務有哪些屬性可以配置
-
事務的傳播性
@Transactional(propagation=Propagation.REQUIRED) 如果有事務, 那么加入事務, 沒有的話新建一個(默認情況下)
-
事務的超時性
@Transactional(timeout=30) //默認是30秒 注意這里說的是事務的超時性而不是Connection的超時性炊豪,這兩個是有區(qū)別的
-
事務的隔離級別
@Transactional(isolation = Isolation.READ_UNCOMMITTED) 讀取未提交數(shù)據(jù)(會出現(xiàn)臟讀, 不可重復讀) 基本不使用
-
回滾
指定單一異常類:@Transactional(rollbackFor=RuntimeException.class) 指定多個異常類:@Transactional(rollbackFor={RuntimeException.class, Exception.class}) 該屬性用于設置需要進行回滾的異常類數(shù)組凌箕,當方法中拋出指定異常數(shù)組中的異常時,則進行事務回滾词渤。
-
只讀
@Transactional(readOnly=true) 該屬性用于設置當前事務是否為只讀事務牵舱,設置為true表示只讀,false則表示可讀寫缺虐,默認值為false芜壁。
Spring配置和使用事務的注意事項
1、在spring配置文件中引入<tx:>命名空間:
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
2高氮、@Transactional 只能被應用到public方法上, 對于其它非public的方法,如果標記了@Transactional也不會報錯,但方法沒有事務功能.
3慧妄、用 spring 事務管理器,由spring來負責數(shù)據(jù)庫的打開,提交,回滾.默認遇到運行期例外
(throw new RuntimeException("注釋");)
會回滾,即遇到不受檢查(unchecked)的例外時回滾剪芍;
而遇到需要捕獲的例外(throw new Exception("注釋");)不會回滾,即遇到受檢查的例外(就是非運行時拋出的異常塞淹,編譯器會檢查到的異常叫受檢查例外或說受檢查異常)時,需我們指定方式來讓事務回滾 要想所有異常都回滾,要加上 @Transactional( rollbackFor={Exception.class,其它異常}) .如果讓unchecked例外不回滾: @Transactional(notRollbackFor=RunTimeException.class)
如下:
@Transactional(rollbackFor=Exception.class) //指定回滾,遇到異常Exception時回滾
public void methodName() {
throw new Exception("注釋");
}
@Transactional(noRollbackFor=Exception.class)//指定不回滾,遇到運行期例外(throw new RuntimeException("注釋");)會回滾
public ItimDaoImpl getItemDaoImpl() {
throw new RuntimeException("注釋");
}
4罪裹、@Transactional 注解應該只被應用到 public 可見度的方法上饱普。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解状共,它也不會報錯套耕, 但是這個被注解的方法將不會展示已配置的事務設置。
5峡继、@Transactional 注解可以被應用于接口定義和接口方法冯袍、類定義和類的 public 方法上。然而碾牌,請注意僅僅 @Transactional 注解的出現(xiàn)不足于開啟事務行為康愤,它僅僅 是一種元數(shù)據(jù)儡循,能夠被可以識別 @Transactional 注解和上述的配置適當?shù)木哂惺聞招袨榈腷eans所使用。上面的例子中翘瓮,其實正是 <tx:annotation-driven/>元素的出現(xiàn) 開啟 了事務行為贮折。
6、Spring團隊的建議是你在具體的類(或類的方法)上使用 @Transactional 注解资盅,而不要使用在類所要實現(xiàn)的任何接口上调榄。你當然可以在接口上使用 @Transactional 注解,但是這將只能當你設置了基于接口的代理時它才生效呵扛。因為注解是 不能繼承 的每庆,這就意味著如果你正在使用基于類的代理時,那么事務的設置將不能被基于類的代理所識別今穿,而且對象也將不會被事務代理所包裝(將被確認為嚴重的)缤灵。因 此,請接受Spring團隊的建議并且在具體的類上使用 @Transactional 注解蓝晒。