說明
前一篇文字《spring事務(wù)之注解形式(一)》發(fā)現(xiàn)只是測(cè)試了情況,并且異常時(shí)屬于RunTimeException的,所以造成我以為加了這個(gè)“@Transactional(readOnly = false, propagation = Propagation.REQUIRED”,就以為所有的都會(huì)回滾,但是我們得代碼里面不一樣,代碼里面是自定義了異常,并且這個(gè)異常集成Exception的,所以經(jīng)過測(cè)試,如果是這樣是不會(huì)回滾的,最后網(wǎng)上搜了看看,并結(jié)合實(shí)際測(cè)試,還是有點(diǎn)理解,所以這篇屬于經(jīng)驗(yàn)之談,哈哈,最后要弄清源碼層次的。
一:拋出Exception異常,情況如下
@Transactional(readOnly = false, propagation = Propagation.REQUIRED,rollbackFor=Exception.class)
public void testException(ParamBean pb) throws Exception {
personInfoSerivice.updateLoginNameException(pb);
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public int updateLoginNameException(ParamBean pb) throws Exception {
Map<String, Object> paramMap = pb.getParamMap();
int i = personInfoMapper.updateLoginName(paramMap);
try{
System.out.println(10/0);
}catch(Exception e){
throw new Exception();
}
return i;
}
1.如果不加rollbackFor=Exception.class,那么此次更新將不會(huì)回滾;如果加上則會(huì)進(jìn)行回滾操作。
2.1.如果加rollbackFor=Exception.class,此次更新則會(huì)進(jìn)行回滾操作。
@Transactional(readOnly = false, propagation = Propagation.REQUIRED,rollbackFor=Exception.class)
public void testExceptionForTwo(ParamMap pb) throws Exception {
System.out.println("---------------------");
personInfoSerivice.updatePerson(pb);
personInfoSerivice.updateLoginNameException(pb);
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRED,rollbackFor=Exception.class)
public int updateLoginNameException(ParamMap pb) throws Exception {
Map<String, Object> paramMap = pb.getParanMap();
int i = personInfoMapper.updateLoginName(headMap);
try{
System.out.println(10/0);
}catch(Exception e){
e.printStackTrace();
throw new Exception();
}
return i;
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW,,rollbackFor=Exception.class)
public int updatePerson(EngineBean pb) {
Map<String, Object> headMap = pb.getHeadMap();
headMap.put("mobile", "86"+headMap.get("mobileNo"));
int i = personInfoMapper.updatePerson(headMap);
return i;
}
1.1如上代碼結(jié)果:
如果兩個(gè)都是一個(gè)是REQUIRES_NEW,updatePerson會(huì)執(zhí)行成功,但是updateLoginNameException會(huì)進(jìn)行回滾操作;
分析:因?yàn)閡pdatePerson中沒有異常拋出,并且是一個(gè)新的事物,所以在updateLoginNameException中拋出異常也不會(huì)影響到updatePerson的回滾。所以如果updateLoginNameException中try...catch沒有拋出異常,則其也會(huì)執(zhí)行成功。
1.2對(duì)于上述代碼其存在的情況:
1:判斷是否是同一個(gè)事物;
2:判斷是否有try...catch異常,try完有沒有拋出異常;如果捕獲了異常,但是沒有拋出異常,相當(dāng)于該方法中沒有異常;如果捕獲到了異常,但是拋出了異常,那么就需要進(jìn)行異常回滾。
二:拋出RunTimeException默認(rèn)會(huì)回滾
比如之前拋出的10/0的異常:
java.lang.ArithmeticException: / by zero屬于運(yùn)行時(shí)異常
對(duì)之前的一篇文章中<a href="http://www.lxweimin.com/p/a4137cf46e65">spring事務(wù)之注解形式(一)</a>,拋出的都是運(yùn)行時(shí)異常,對(duì)于運(yùn)行時(shí)異常,加了事物注解,spring會(huì)默認(rèn)進(jìn)行回滾操作.spring文檔中有說明如下:
看RunTimeException那段意思是:
Spring框架的事務(wù)基礎(chǔ)架構(gòu)代碼將默認(rèn)地 只 在拋出運(yùn)行時(shí)和unchecked exceptions時(shí)才標(biāo)識(shí)事務(wù)回滾。 也就是說,當(dāng)拋出一個(gè) RuntimeException
或其子類例的實(shí)例時(shí)。(Errors
也一樣 - 默認(rèn)地 - 標(biāo)識(shí)事務(wù)回滾。)從事務(wù)方法中拋出的Checked exceptions將不 被標(biāo)識(shí)進(jìn)行事務(wù)回滾。
異常
異常其實(shí)分unchecked exceptions和checked exceptions,我們主要關(guān)注unchecked的異常,對(duì)于unchecked的異常又分"運(yùn)行時(shí)異常"和“非運(yùn)行時(shí)異常”,網(wǎng)上看見了一片文章覺得很贊,<a >深入理解java異常處理機(jī)制</a>;先借鑒下,后面看看自己也總結(jié)下自己的理解,哈哈。
NEXT
昨天下班后跟今天早上來公司加班,又專門的來測(cè)試了幾種情況,主要還是要看上面所說的,是否是同一個(gè)事物,有沒有進(jìn)行異常捕獲,捕獲后有沒有拋出都會(huì)影響事物的回滾等。之前也是一直都只是會(huì)用,使用xml形式的方式,這次使用注解,才有點(diǎn)深入的理解了些,但是還不夠,底層的源碼部分還是沒有理解,現(xiàn)在只是理解了注解形式的配置而已,所以下面還有深入的分析,希望自己能搞定這種源碼理解,最后,你會(huì)發(fā)現(xiàn),只有自己嘗試做過,遇到的東西才會(huì)理解的更深刻。
浩語
__
__ _ ____ __| |__ _____ ___
\ \/ \/ / | \ | \\__ \ / _ \
\ /| | / Y \/ __ \( <_> )
\/\_/ |____/|___| (____ /\____/
\/ \/
走在自己的路上,遇到要遇到的人,經(jīng)歷要經(jīng)歷的事,這才是我們需要面對(duì)的。