1. 程式人生 > >Spring中事務的問題

Spring中事務的問題

spring的使用處理方式有兩種:宣告式事務和程式設計式事務;
下面說一下主要使用的宣告式事務使用過程的問題,如果沒有事務巢狀的話事務處理很簡單,事務處理過程異常拋到切面上又切面負責回滾,如果事務處理正常則又切面負責提交即可。
事務之所以複雜是因為有巢狀事務的問題,當事務巢狀是就需要進行事務傳遞方面的考慮:
@Transactional(propagation = Propagation.MANDATORY)---強制的(必須有transaction)
@Transactional(propagation = Propagation.NESTED)----------內嵌的transaction
@Transactional(propagation = Propagation.NEVER)------------絕不能有transaction
@Transactional(propagation = Propagation.NOT_SUPPORTED)--方法要執行,遇到的transaction掛起。
@Transactional(propagation = Propagation.REQUIRED)   --------------必須的(預設的)
@Transactional(propagation = Propagation.REQUIRES_NEW)---------方法要執行,遇到的transaction掛起,建立新的transaction。
@Transactional(propagation = Propagation.SUPPORTS)----------------有沒有無所謂

例如下面程式碼:程式碼1:

@Transactional(rollbackFor=Exception.class)
public void execute(){
PayCenterTTaskCtl taskCtl = new PayCenterTTaskCtl();
taskCtl.setTASK_TYPE("tt");
taskCtl.setTASK_SEQ("2089980123992");
taskCtl.setTASK_STAT(TaskStatEnums.失敗.getValue());
taskCtl.setS_TOT(50);
taskCtl.setF_TOT(50);
taskCtl.setUPD_TIME(new Date());
batchControlUtil.updateByTaskTypeAndSeq(taskCtl);
try{
((TestTranscation)AopContext.currentProxy()).inserTest(taskCtl);
}catch(Exception e){
System.err.println("異常");
}

}@Transactional(rollbackFor=Exception.class)
public void inserTest(PayCenterTTaskCtl taskCtl){
batchControlUtil.insertTTaskCtl("tt", "2089980123992", 100);
}
程式碼2:
@Transactional(rollbackFor=Exception.class)
public void execute(){
PayCenterTTaskCtl taskCtl = new PayCenterTTaskCtl();
taskCtl.setTASK_TYPE("tt");
taskCtl.setTASK_SEQ("2089980123992");
taskCtl.setTASK_STAT(TaskStatEnums.失敗.getValue());
taskCtl.setS_TOT(50);
taskCtl.setF_TOT(50);
taskCtl.setUPD_TIME(new Date());
batchControlUtil.updateByTaskTypeAndSeq(taskCtl);
try{
((TestTranscation)AopContext.currentProxy()).inserTest(taskCtl);
}catch(Exception e){
System.err.println("異常");
}
}

@Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW)
public void inserTest(PayCenterTTaskCtl taskCtl){
batchControlUtil.insertTTaskCtl("tt", "2089980123992", 100);
}
下面解釋一下兩種事務的不同之處:

1、首先需要宣告一下,上面的方法呼叫都是同一個類中的呼叫,為了能夠使註解事務生效使用了AOP的方式進行了呼叫,如果是通過動態注入的話就不需要使用AOP方式了;

2、事務巢狀導致事務之間具有傳遞性,如果都使用預設的方式,第一個事務啟動後後其他的事務都將繼承此事務,導致的現象是當某個子事務處理失敗後,就會將整個事務標記為失敗,當處理回到父方法時就會將所有資料庫操作都回滾調。

3、為了使子事務不影響父事務的執行,就需要將子事務的傳播方式修改為REQUIRES_NEW