做旅游網站推廣色盲怎么治療
事務失效的八大情況
一、非public修飾的方法
@Transactional注解只能在在public修飾的方法下使用。
/*** 私有方法上的注解,不生效(因私有方法Spring掃描不到該方法,所以無法生成代理)*/
@Transactional
private boolean test() {//test code
}
二、類內部訪問
類內部非直接訪問帶注解標記的方法 B,而是通過類普通方法 A,然后由 A 調用 B。 自己玩自己
@Service
public class Demo {public void A() {this.B();}@Transactionalpublic void B() {......}
}
- 在該Service類中使用AopContext.currentProxy()獲取代理對象
@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)//啟用 AspectJ 的自動代理功能
@EnableTransactionManagement//允許使用事務注解,開啟事務管理的支持
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args);}
}
((ServiceA)AopContext.currentProxy()).doSave(user);
@EnableTransactionManagement 的作用是:
1.開啟 Spring 的事務管理功能。
2.通過 AOP(面向切面編程)的方式,為被 @Transactional 注解的方法添加事務控制邏輯。
3.確保事務的正確開啟、提交或回滾。
@EnableAspectJAutoProxy(exposeProxy = true) 的作用是:
1.開啟 Spring AOP 的自動代理功能。
2.使用 AspectJ 作為 AOP 框架,實現橫切關注點的織入。
3.允許通過 AopContext 暴露代理對象,使得其他組件可以獲取到代理對象。
三、數據庫不支持事務
MySQL中,MyISAM引擎不支持事物,InnoDB 支持事物
四、異常類型不匹配
@Transactional 注解默認只處理運行時異常( RuntimeException 和 error),而不會處理受檢異常( Exception 的子類)。當拋出未被捕獲的運行時異常時,Spring 會觸發(fā)事務回滾操作,將之前的操作撤銷;而對于未被捕獲的受檢異常,Spring 不會觸發(fā)事務回滾操作。如果需要處理受檢異常并觸發(fā)事務回滾,可以通過 rollbackFor 和 noRollbackFor 屬性來指定需要回滾或不需要回滾的異常類型。
/**
* 非運行異常,且沒有通過 rollbackFor 指定拋出的異常,不生效
*
* @param id
* @return
* @throws Exception
*/@Transactionalpublic void insertAll(PoMaster master) throws Exception {poMasterDao.insert(master);if(1 == 1){throw new Exception("測試異常");}poItemDao.insertList(master.getItems());}
五、傳播屬性設置問題
propagation屬性錯誤
@Transactional默認的事務傳播機制是:REQUIRED,若指定成了NOT_SUPPORTED、NEVER事務傳播機制,則事物不生效,如:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
六、捕獲異常未拋出
@Transactional
public void A(){try{......}catch(Exception e){// 未拋異常}
}
七、Bean沒有納入Spring IOC容器管理
// 注釋調@Component,該類沒被Spring管理,事物也是不生效的
// 注釋調@Component,該類沒被Spring管理,事物也是不生效的
public class Demo {@Transactional(rollbackFor = Exception.class)public void A() {......}
}
八、事務方法內啟動新線程進行異步操作
主線程執(zhí)行過程中,調用了一個新的線程執(zhí)行任務,在子線程使用過程中,如果發(fā)送異常,由于進程是異步的,所以主進程無法感知到,不會進行回滾,此時事務失效了。
@Transactional(rollbackFor= BizException.class)public int transfer2(String from,String to, int money){accountDao.decrMoney(from,money);new Thread(()->{int c = 5/0;accountDao.addMoney(to,money);}).start();return 1;}