之前去面試的時候,被問到一句spring嵌套事務的情況怎么解決,被問到啞口無言,恰好現在的專案正好用到嵌套事務,并且也正在嘗試分布式事務,所以現在也是自己學習了一些嵌套事務相關的東西,
事務隔離級別的概念
事務傳播 - Propagation
REQUIRED: 使用當前的事務,如果當前沒有事務,則自己新建一個事務,子方法是必須運行在一個事務中的;
如果當前存在事務,則加入這個事務,成為一個整體,
舉例:領導沒飯吃,我有錢,我會自己買了自己吃;領導有的吃,會分給你一起吃,
SUPPORTS: 如果當前有事務,則使用事務;如果當前沒有事務,則不使用事務,
舉例:領導沒飯吃,我也沒飯吃;領導有飯吃,我也有飯吃,
MANDATORY: 該傳播屬性強制必須存在一個事務,如果不存在,則拋出例外
舉例:領導必須管飯,不管飯沒飯吃,我就不樂意了,就不干了(拋出例外)
REQUIRES_NEW: 如果當前有事務,則掛起該事務,并且自己創建一個新的事務給自己使用;
如果當前沒有事務,則同 REQUIRED
舉例:領導有飯吃,我偏不要,我自己買了自己吃
NOT_SUPPORTED: 如果當前有事務,則把事務掛起,自己不適用事務去運行資料庫操作
舉例:領導有飯吃,分一點給你,我太忙了,放一邊,我不吃
NEVER: 如果當前有事務存在,則拋出例外
舉例:領導有飯給你吃,我不想吃,我熱愛作業,我拋出例外
NESTED: 如果當前有事務,則開啟子事務(嵌套事務),嵌套事務是獨立提交或者回滾;
如果當前沒有事務,則同 REQUIRED,
但是如果主事務提交,則會攜帶子事務一起提交,
如果主事務回滾,則子事務會一起回滾,相反,子事務例外,則父事務可以回滾或不回滾,
舉例:領導決策不對,老板怪罪,領導帶著小弟一同受罪,小弟出了差錯,領導可以推卸責任,
幾種不同情況的嘗試
父子事務均無事務隔離級別
@Service
public class StuServiceImpl implements StuService {
@Autowired
StuMapper stuMapper;
@Override
//@Transactional
public void saveStuChild() {
saveChildren1();
int i =1/0;
saveChildren2();
}
public void saveChildren1(){
Stu stu = new Stu();
stu.setAge(11);
stu.setName("test1");
stuMapper.insert(stu);
}
public void saveChildren2(){
Stu stu = new Stu();
stu.setAge(22);
stu.setName("test1");
stuMapper.insert(stu);
}
@Override
//@Transactional(propagation = Propagation.REQUIRED)
public void saveStuParent() {
Stu stu = new Stu();
stu.setAge(30);
stu.setName("parent");
stuMapper.insert(stu);
}
}
父級事務的情況
@Service
public class TestTransServiceImpl implements TestTransService {
@Autowired
StuService stuService;
@Override
public void saveStudent() {
stuService.saveStuParent();
stuService.saveStuChild();
}
}
@Test
public void TestNoTransactional(){
testTransService.saveStudent();
}
例外之前的資料都被保存了,例外之后的資料都沒有保存

父事務有Required級別事務,子事務無事務
@Service
public class TestTransServiceImpl implements TestTransService {
@Autowired
StuService stuService;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void saveStudent() {
stuService.saveStuParent();
stuService.saveStuChild();
}
}
stuService代碼相同

事務全部回滾,資料均沒有插入資料庫,即當子事務沒有事務時,子方法是同樣在一個事務的,即事務被傳遞到了子事務
子事務有Required級別事務,父事務無事務
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void saveStuChild() {
saveChildren1();
int i =1/0;
saveChildren2();
}

可以看到子事務只會影響到子事務,父事務不會被影響,父事務沒有事務的方法不受影響
子事務為support級別事務,父方法有事務或無事務的兩種情況
- 父方法無事務子方法無事務時,加上注解 @Transactional(propagation = Propagation.SUPPORTS)
@Transactional(propagation = Propagation.SUPPORTS)
public void saveStuChild() {
saveChildren1();
int i =1/0;
saveChildren2();
}

j即跟初始狀態無事務的狀態一樣
- 父方法事務級別為required,同理可以這種情況跟之前一樣也是無法插入資料
子方法事務級別為MANDATORY
Propagation.MANDATORY要求必須為事務包裹,否則會拋出例外
子方法事務級別為REQUIRES_NEW
如果當前有事務,則掛起該事務,并且自己創建一個新的事務給自己使用;即自己用自己的事務,如果當前沒有事務,則同 REQUIRED,同樣是自己使用自己的事務
子方法事務隔離級別為NOT_SUPPORTED,即不支持事務
父方法同樣無事務注解的情況下和無事務的情況一樣的,
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void saveStuChild() {
saveChildren1();
int i =1/0;
saveChildren2();
}
子方法事務隔離級別為NEVER,
如果父方法有事務則會拋出例外
子方法事務隔離級別為NESTED
如果當前有事務,則開啟子事務(嵌套事務),嵌套事務是獨立提交或者回滾; 如果當前沒有事務,則同 REQUIRED, 但是如果主事務提交,則會攜帶子事務一起提交, 如果主事務回滾,則子事務會一起回滾,相反,子事務例外,則父事務可以回滾或不回滾,
當父方法有事務且發生例外時,子事務一起回滾,當子事務發生例外時,服務器try.catch之后可以選擇不回滾
日常用到最多的就是這種模式,剛好最近也用上了,
歡迎搜索關注本人與朋友共同開發的微信面經小程式【大廠面試助手】和公眾號【微瞰技術】


轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/235000.html
標籤:其他
