問題闡述及解決程序
現在需要寫一個定時任務,其處理程序要在for回圈進行,并且回圈體中要呼叫兩個方法,大致代碼是這樣的:
1 public void regionRecoveryProtectionPeriod() { 2 for (????) { 3 try { 4 method1(); 5 method2(); 6 } catch (Exception e){ 7 log.error("",e.getMessage()); 8 } 9 } 10 }
用try將回圈體包裹起來防止回圈中斷,但是這段存在一個問題——回圈體中沒有用事務管理,這將會造成很嚴重的后果,
很容易想到的方法就是將回圈體單獨寫到一個方法里,將這個新的方法上加事務,代碼如下:
1 public void regionRecoveryProtectionPeriod() { 2 for (????) { 3 try { 4 this.releaseOrigin(); 5 } catch (Exception e){ 6 log.error("",e.getMessage()); 7 } 8 } 9 10 @Transactional(rollbackFor = Exception.class) 11 void releaseOrigin() { 12 method1(); 13 method2(); 14 }
這段代碼看似沒有問題,但是經過試驗,發現事務并沒有起作用,和原來的結果沒有任何區別,
原因是自呼叫不走代理物件,所以用this.呼叫內層方法時注解是不生效的,因此要通過代理物件的方式呼叫內層方法:Object proxy = AopContext.currentProxy();
代碼如下:
public void regionRecoveryProtectionPeriod() { Service proxy = (Service)AopContext.currentProxy(); for (????) { try { proxy.releaseOrigin(); } catch (Exception e){ log.error("",e.getMessage()); } } @Transactional(propagation = Propagation.NESTED,rollbackFor = Exception.class) void releaseOrigin() { method1(); method2(); }
這樣做的話,內部事務就能正常生效了,由于外層的方法通常也是要加事務的,所以內層的事務要加上propagation = Propagation.NESTED讓內層事務不會影響到外層事務,
總結
關于這種問題的解決方案有人說可以將內層事務的方法寫在別的service里,或者自己注入自己,代理物件的方法里用了ThreadLocal里的get方法,不知道是否會對性能有啥影響,如果有更好的方法的話可以交流一下
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/257975.html
標籤:Java
