成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Spring 踩坑之@Transactional 神奇失效

derek_334892 / 2586人閱讀

摘要:引言對(duì)于追求數(shù)據(jù)強(qiáng)一致性的系統(tǒng),事務(wù)扮演者十分重要的角色最近在項(xiàng)目中遇到一個(gè)事務(wù)失效的問(wèn)題,在此分享給大家。情景回放問(wèn)題分析初步分析這是事務(wù)獲取鎖超時(shí)導(dǎo)致的錯(cuò)誤,奇怪的是拋出異常但是事務(wù)沒(méi)有回滾。唯一的解釋是事務(wù)失效了。

引言

對(duì)于追求數(shù)據(jù)強(qiáng)一致性的系統(tǒng),事務(wù)扮演者十分重要的角色.最近在項(xiàng)目中遇到一個(gè)事務(wù)失效的問(wèn)題,在此分享給大家。

情景回放
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
; SQL []; Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:259)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
    at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
    at com.sun.proxy.$Proxy121.update(Unknown Source)
    at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:294)
    at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:62)
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
問(wèn)題分析

初步分析這是事務(wù)獲取鎖超時(shí)導(dǎo)致的錯(cuò)誤,奇怪的是拋出異常但是事務(wù)沒(méi)有回滾?;蛟S你們說(shuō)MySQLTransactionRollbackException是檢查性異常(@Transactional默認(rèn)只捕獲非檢查性異常),但是項(xiàng)目添加了注解: @Transactional(rollbackFor = Exception.class)。唯一的解釋是——事務(wù)失效了。

 ProductService.java
/**********************************************************************/
public interface ProductService{
    Integer getPrice(ProductInfo p);
    Integer compute(ProductInfo p);
}
/**********************************************************************/


ProductServiceImpl.java
/**********************************************************************/
@Service
public class ProductServiceImpl implements ProductService{

    public Integer getPrice(ProductInfo p){
        ...
        compute(p);
        ...
    }

    @Transactional(rollbackFor = Exception.class)
    public Integer compute(ProductInfo p){ //TestService的普通方法
        try{
            ...
        }catch(Exception e){
             e.printStackTrace();
             return -1;
        }
    }
}
/**********************************************************************/

初看這段代碼,沒(méi)啥毛病啊。噢,不對(duì),compute 方法內(nèi)部catch了異常,spring aop無(wú)法捕獲異常。如果需要捕獲異常,需要手動(dòng)回滾,于是compute方法修改如下:

    @Transactional(rollbackFor = Exception.class)
        public Integer compute(ProductInfo p){ //TestService的普通方法
            try{
                ...
            }catch(Exception e){
                 e.printStackTrace();
                 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//手動(dòng)回滾事務(wù)
                 return 0;
            }
        }

繼續(xù)運(yùn)行,結(jié)果發(fā)現(xiàn)事務(wù)還是未生效。通過(guò)查詢資料發(fā)現(xiàn),service方法直接調(diào)用了本類的一個(gè)方法(沒(méi)有通過(guò)接口調(diào)用),該方法上的事務(wù)將不會(huì)生效。

解決方案

想啟用本類的普通方法的事務(wù),通過(guò)接口來(lái)調(diào)用該方法即可生效。如果先在方法內(nèi)部catch異常,需要添加TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();否則可以在外面捕獲這個(gè)異常。下面是在方法內(nèi)部捕獲異常的示例:

 ProductService.java
/**********************************************************************/
public interface ProductService{
    Integer getPrice(ProductInfo p);
    Integer compute(ProductInfo p);
}
/**********************************************************************/


ProductServiceImpl.java
/**********************************************************************/
@Service
public class ProductServiceImpl implements ProductService{
    @Autowired
    private ProductService productService;
    
    public Integer getPrice(ProductInfo p){
        productService.compute(p);
    }

    @Transactional(rollbackFor = Exception.class)
    public Integer compute(ProductInfo p){ 
        try{
            ...
        }catch(Exception e){
             e.printStackTrace();
             TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
             return 0;
        }
    }
}
/**********************************************************************/
總結(jié)

Spring Transactional一直是RD的事務(wù)神器,但是如果用不好,反會(huì)傷了自己。下面總結(jié)@Transactional經(jīng)常遇到的幾個(gè)場(chǎng)景:

@Transactional 加于private方法, 無(wú)效
@Transactional 加于未加入接口的public方法, 再通過(guò)普通接口方法調(diào)用, 無(wú)效
@Transactional 加于接口方法, 無(wú)論下面調(diào)用的是private或public方法, 都有效
@Transactional 加于接口方法后, 被本類普通接口方法直接調(diào)用, 無(wú)效
@Transactional 加于接口方法后, 被本類普通接口方法通過(guò)接口調(diào)用, 有效
@Transactional 加于接口方法后, 被它類的接口方法調(diào)用, 有效
@Transactional 加于接口方法后, 被它類的私有方法調(diào)用后, 有效

Transactional是否生效, 僅取決于是否加載于接口方法, 并且是否通過(guò)接口方法調(diào)用(而不是本類調(diào)用)。

如果大家有更好的方法,歡迎加入討論!

參考博客:https://www.cnblogs.com/milto...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69240.html

相關(guān)文章

  • C3的坑之inline-block

    最近開始復(fù)習(xí)css一直在踩坑,今天分享一個(gè)inline-block 關(guān)于inline-block可能很多人都不熟悉,布局這方面很多人用的都是flex或者浮動(dòng),flex很強(qiáng)大毋庸置疑的可是關(guān)于兼容性就不是很讓人滿意,而浮動(dòng)雖然很兼容可是覺(jué)得清除浮動(dòng)就很麻煩,于此我在一些大型網(wǎng)站,例如我們的segmentfault的首頁(yè)導(dǎo)航展示用的布局就是inline-block,覺(jué)得inline-block可以擼一...

    luck 評(píng)論0 收藏0
  • C3的坑之inline-block

    最近開始復(fù)習(xí)css一直在踩坑,今天分享一個(gè)inline-block 關(guān)于inline-block可能很多人都不熟悉,布局這方面很多人用的都是flex或者浮動(dòng),flex很強(qiáng)大毋庸置疑的可是關(guān)于兼容性就不是很讓人滿意,而浮動(dòng)雖然很兼容可是覺(jué)得清除浮動(dòng)就很麻煩,于此我在一些大型網(wǎng)站,例如我們的segmentfault的首頁(yè)導(dǎo)航展示用的布局就是inline-block,覺(jué)得inline-block可以擼一...

    zengdongbao 評(píng)論0 收藏0
  • 小程序坑之獲取不到e.target.dataset的值

    摘要:在頁(yè)面與傳值中我們經(jīng)常用到的方式,然后通過(guò)取的值今天在獲取值時(shí)怎么也取不到,后來(lái)發(fā)現(xiàn)對(duì)象有和屬性,而就在中,所以通過(guò)取到了正確的值。另外最好不要用駝峰命名如,這樣有時(shí)候也取不到值。 在頁(yè)面與js傳值中我們經(jīng)常用到data-id=1的方式,然后通過(guò)e.target.dataset.id取id的值今天在獲取值時(shí)怎么也取不到,后來(lái)發(fā)現(xiàn)e對(duì)象有currentTarget和target屬性,而d...

    韓冰 評(píng)論0 收藏0
  • 小程序坑之showModal:fail parameter error

    摘要:提示原因是對(duì)象中的值應(yīng)該為字符串正確的賦值打開方式應(yīng)該是不得不說(shuō)小程序中的坑真多,賦值類型還得是字符串 console提示:showModal:fail parameter error: parameter.content should be String instead of Undefined;原因是 Page({ data: { userInfo: {}, h...

    biaoxiaoduan 評(píng)論0 收藏0
  • 小程序坑之獲取不到e.target.dataset的值

    摘要:在頁(yè)面與傳值中我們經(jīng)常用到的方式,然后通過(guò)取的值今天在獲取值時(shí)怎么也取不到,后來(lái)發(fā)現(xiàn)對(duì)象有和屬性,而就在中,所以通過(guò)取到了正確的值。另外最好不要用駝峰命名如,這樣有時(shí)候也取不到值。 在頁(yè)面與js傳值中我們經(jīng)常用到data-id=1的方式,然后通過(guò)e.target.dataset.id取id的值今天在獲取值時(shí)怎么也取不到,后來(lái)發(fā)現(xiàn)e對(duì)象有currentTarget和target屬性,而d...

    Turbo 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<