Spring事務傳播

在TransactionDefinition接口中定義了七個事務傳播行爲

PROPAGATION_REQUIRED 如果存在一個事務,則支持當前事務。如果沒有事務則開啓一個新的事務。默認行爲

PROPAGATION_SUPPORTS 如果存在一個事務,支持當前事務。如果沒有事務,則非事務的執行。但是對於事務同步的事務管理器,PROPAGATION_SUPPORTS與不使用事務有少許不同。

PROPAGATION_MANDATORY 如果已經存在一個事務,支持當前事務。如果沒有一個活動的事務,則拋出異常。

PROPAGATION_REQUIRES_NEW 總是開啓一個新的事務。如果一個事務已經存在,則將這個存在的事務掛起。

PROPAGATION_NOT_SUPPORTED 總是非事務地執行,並掛起任何存在的事務。

PROPAGATION_NEVER 總是非事務地執行,如果存在一個活動事務,則拋出異常

PROPAGATION_NESTED如果一個活動的事務存在,則運行在一個嵌套的事務中. 如果沒有活動事務, 則按TransactionDefinition.PROPAGATION_REQUIRED 屬性執行

本文重點講解PROPAGATION_REQUIRED 、PROPAGATION_REQUIRES_NEW、 PROPAGATION_NESTED

實際應用中常常存在serviceA調用serviceB的情況。那具體情況下serviceA和serviceB之間的事務又是怎麼傳遞的呢。

例子1:

/** 事務默認是required*/
//@Transactional
@Service("userService")
public class UserServiceImpl implements UserServive {
@Autowired
private UserMapper userDao;


@Autowired
private CommonService commonService;


public List<UserInfo> getUsers() {

return userDao.selectUsers();
}

@Transactional(propagation = Propagation.REQUIRED)
public void updateUserAgeById(int age, long id) {

userDao.updateUserInfoById(age, id);

commonService.updateUserExtById("未知", 1);

//int b = 1/0;

/* try {
commonService.updateUserExtById("未知", 1);
} catch (Exception e) {
// TODO: handle exception
}*/
}
}

//@Transactional
@Service("commonService")
public class CommonServiceImpl implements CommonService {

@Autowired
private UserMapper userDao;

// 如果出現運行時異常,此處會回滾 並對外拋出異常
@Transactional(propagation = Propagation.NESTED)
public void updateUserExtById(String address, long id) {

userDao.updateUserExtById(address, id);

int a = 1/0;
}
}

此例userservice中的updateUserAgeById事務聲明爲Propagation.REQUIRED,調用commonservice中的updateUserExtById方法。且此方法事務聲明爲Propagation.NESTED。按上面的解釋commonservice將運行在嵌套事務中。經過測試,當updateUserExtById

發生異常時,自身進行回滾操作,回滾到它執行之前的savepoint。並向外拋出異常,userservice可以對異常進行捕獲視情況選擇回滾還是不回滾。如果不進行任何處理同樣數據會發生回滾。

例子2:

@Transactional(propagation = Propagation.REQUIRED)
public void updateUserAgeById(int age, long id) {

userDao.updateUserInfoById(age, id);

commonService.updateUserExtById("未知", 1);

int b = 1/0;


// 如果出現運行時異常,此處會回滾 並對外拋出異常
@Transactional(propagation = Propagation.NESTED)
public void updateUserExtById(String address, long id) {

userDao.updateUserExtById(address, id);

//int a = 1/0;
}

異常發生在userservice方法中,因爲屬於嵌套事務,所以userservice和commonservice都會發生回滾。

例子3:

@Transactional(propagation = Propagation.REQUIRED)
public void updateUserAgeById(int age, long id) {

userDao.updateUserInfoById(age, id);

commonService.updateUserExtById("未知", 1);

//int b = 1/0;


// 如果出現運行時異常,此處會回滾 並對外拋出異常
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUserExtById(String address, long id) {

userDao.updateUserExtById(address, id);

int a = 1/0;
}

此處模擬的是commonservice使用的是Propagation.REQUIRES_NEW。userservice中的事務會被掛起。commonservice會新開一個事務。經過測試,此處模擬commonservice異常,其對應的事務會回滾。同樣此處會對外拋出異常,userservice視情況對異常處理,選擇回滾還是不回滾。

例子4:

@Transactional(propagation = Propagation.REQUIRED)
public void updateUserAgeById(int age, long id) {

userDao.updateUserInfoById(age, id);

commonService.updateUserExtById("未知", 1);

int b = 1/0;


// 如果出現運行時異常,此處會回滾 並對外拋出異常
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUserExtById(String address, long id) {

userDao.updateUserExtById(address, id);

//int a = 1/0;
}

此處模擬userservice發生異常。我們猜測一下commonservice會不會回滾。經過試驗得到結果是commonservice不會回滾。因爲在userservice發生異常前。commonservice的事務已經commit。

例子5:

@Transactional(propagation = Propagation.REQUIRED)
public void updateUserAgeById(int age, long id) {

userDao.updateUserInfoById(age, id);

//commonService.updateUserExtById("未知", 1);

//int b = 1/0;

try {
commonService.updateUserExtById("未知", 1);
} catch (Exception e) {
// TODO: handle exception
}
}

@Transactional(propagation = Propagation.REQUIRED)
public void updateUserExtById(String address, long id) {

userDao.updateUserExtById(address, id);

int a = 1/0;
}

最後再來看看同用Propagation.REQUIRED的情況。此處模擬commonservice異常,不用懷疑commonservice肯定會回滾。但是此處userservice進行了異常捕獲,userservice還會回滾嗎?答案是不會。因爲commonservice根本不會拋出異常。兩者用的是一個事務,commonservice發生異常,整個事務直接rollback。

好了,大概清楚了spring事務的傳播關係。網上有很多傳播的關係,但是都講的雲裏霧裏的。所以特此文章記錄一下。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章