目錄
一、方法使用try/catch。
二、同類中方法的互相調用。
一、方法使用try/catch。
失效代碼
@Override
@Transactional
public RrcResponse addShopingCart(AddShopingCartModel addShopingCartModel) {
RrcResponse response = new RrcResponse(CodeMsg.SUCCESS);
//校驗參數
OrderCart cart = OrderTransfModel.getOrderCart(addShopingCartModel);
if (!validateForInsert(cart)) {
return new RrcResponse(CodeMsg.POC_ERROR_PARAMETER);
}
try {
cart.setStatus(ConstantsEnum.ORDERCART_STATUS_ADD.getIndexInt());
EntityUtils.setCreatAndUpdatInfo(cart);
mapper.insertSelective(cart);
int i = 1/0;
} catch (Exception e) {
return new RrcResponse(CodeMsg.POC_ERROR_ADDCART);
}
return response;
}
失效原因:被攔截的方法需顯式抛出異常,并不能經任何處理,這樣aop代理才能捕獲到方法的異常,才能進行復原,預設情況下aop隻捕獲runtimeexception的異常。
解決方案
1.在catch中手動throw new 你的異常。
throw new RuntimeException();
2.手動執行復原。
try {
cart.setStatus(ConstantsEnum.ORDERCART_STATUS_ADD.getIndexInt());
EntityUtils.setCreatAndUpdatInfo(cart);
mapper.insertSelective(cart);
int i = 1/0;
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return new RrcResponse(CodeMsg.POC_ERROR_ADDCART);
}
二、同類中方法的互相調用。
失效代碼
@Service
public class TestService {
@Override
public RrcResponse addShopingCart(AddShopingCartModel addShopingCartModel) {
RrcResponse response = new RrcResponse(CodeMsg.SUCCESS);
test(cart);
int i = 1/0;
return response;
}
@Transactional
public void test(OrderCart cart) {
EntityUtils.setCreatAndUpdatInfo(cart);
mapper.insertSelective(cart);
}
}
生效代碼 注解互換位置 或另外加一個service調用 不在同一類當中
@Service
public class TestService {
@Override
@Transactional
public RrcResponse addShopingCart(AddShopingCartModel addShopingCartModel) {
RrcResponse response = new RrcResponse(CodeMsg.SUCCESS);
test(cart);
int i = 1/0;
return response;
}
public void test(OrderCart cart) {
EntityUtils.setCreatAndUpdatInfo(cart);
mapper.insertSelective(cart);
}
}
原因說明 動态代理的緣故(這裡是轉載的:https://blog.csdn.net/qq_34021712/article/details/75949779)
1.在需要事務管理的地方加@Transactional 注解。@Transactional 注解可以被應用于接口定義和接口方法、類定義和類的 public 方法上。
[email protected] 注解隻能應用到 public 可見度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不會報錯, 但是這個被注解的方法将不會展示已配置的事務設定。
3.注意僅僅 @Transactional 注解的出現不足于開啟事務行為,它僅僅 是一種中繼資料。必須在配置檔案中使用配置元素,才真正開啟了事務行為。(spring配置檔案中,開啟聲明式事務)
4.通過 元素的 “proxy-target-class” 屬性值來控制是基于接口的還是基于類的代理被建立。如果 “proxy-target-class” 屬值被設定為 “true”,那麼基于類的代理将起作用(這時需要CGLIB庫cglib.jar在CLASSPATH中)。如果 “proxy-target-class” 屬值被設定為 “false” 或者這個屬性被省略,那麼标準的JDK基于接口的代理将起作用。
5.Spring團隊建議在具體的類(或類的方法)上使用 @Transactional 注解,而不要使用在類所要實作的任何接口上。在接口上使用 @Transactional 注解,隻能當你設定了基于接口的代理時它才生效。因為注解是 不能繼承 的,這就意味着如果正在使用基于類的代理時,那麼事務的設定将不能被基于類的代理所識别,而且對象也将不會被事務代理所包裝。
[email protected]的事務開啟 ,或者是基于接口的 或者是基于類的代理被建立。是以在同一個類中一個無事務的方法調用另一個有事務的方法,事務是不會起作用的。