前言:業務需要,最多隻能綁定5個,目前不考慮集羣,單體服務下的內容
第一版代碼:
@Transactional(rollbackFor = {CommonException.class}, propagation = Propagation.REQUIRED)
public Object bindCommonUsedPatient(CommonUsedPatientRequest commonUsedPatientRequest, User user) throws CommonException, ParseException {
synchronized (this){
//查詢總綁定個數 超過則拋出異常
//未超過 則向數據庫插入一條數據 佔位 使用了事務
}
//執行其它邏輯
}
失效原因:同步代碼塊在事務中,一個事務插入了一條數據之後,在執行其它邏輯,並未完成事務時,另一個線程在另一個事務中無法看見之前插入的數據,導致統計數量失效
第二版代碼:
@Transactional(rollbackFor = {CommonException.class}, propagation = Propagation.REQUIRED)
public Object bindCommonUsedPatient(CommonUsedPatientRequest commonUsedPatientRequest, User user) throws CommonException, ParseException {
checkCommonUsedPatientAndInsert();
//執行其它邏輯
}
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public synchronized CommonUsedPatient checkCommonUsedPatientAndInsert(CommonUsedPatientRequest commonUsedPatientRequest, User user) throws CommonException {
//查詢總綁定個數 超過則拋出異常
//未超過 則向數據庫插入一條數據 佔位 使用了事務
}
改進方法:將插入數據庫的操作封裝爲方法,並指定事務的傳播行爲爲 REQUIRES_NEW
失效原因:加註解都是生成代理類,事務的功能都在代理類內部,實例方法A調用實例方法B是直接調用,不走代理類,所以事務未生效
第三版代碼:
將 checkCommonUsedPatientAndInsert 方法寫到另外的 類中,測試OK