這樣的情景可能不常見蜗帜,但是還是會(huì)有的厅缺,一旦遇到,如果業(yè)務(wù)比較復(fù)雜诀豁,就會(huì)很麻煩舷胜,但是還是有解決的方案的活翩,比如將一個(gè)service方法拆成兩個(gè)方法材泄,也就是將兩個(gè)操作的事務(wù)分開。
但是這只適用與業(yè)務(wù)比較簡(jiǎn)單的峦树,如果出現(xiàn)多次數(shù)據(jù)庫(kù)的寫操作簿废,而我們調(diào)用的系統(tǒng)只需要其中一個(gè)寫操作的最新數(shù)據(jù)族檬,如果我們將它分開单料,那么如果調(diào)用目標(biāo)系統(tǒng)出現(xiàn)異常的時(shí)候扫尖,那么之前的寫操作就不能回滾了换怖。
舉個(gè)簡(jiǎn)單的例子:
@Service
publicclassServiceA{
@Transactional
publicvoiddoSomething(){
向數(shù)據(jù)庫(kù)中添加數(shù)據(jù);
調(diào)用其他系統(tǒng);
}
}
這里就用偽代碼來做示例了沉颂,當(dāng)我們執(zhí)行了“向數(shù)據(jù)庫(kù)中添加數(shù)據(jù)”铸屉,我們?nèi)?shù)據(jù)庫(kù)中查詢彻坛,發(fā)現(xiàn)并沒有我們添加的數(shù)據(jù)踏枣,但是當(dāng)我們的service這個(gè)方法執(zhí)行完成之后钙蒙,數(shù)據(jù)庫(kù)中就有這條數(shù)據(jù)了茵瀑,這是由于數(shù)據(jù)庫(kù)的隔離性造成的。
Spring中的事務(wù)注解@transactional提供了一個(gè)參數(shù):
Propagationpropagation()defaultPropagation.REQUIRED;
這個(gè)參數(shù)是定義Spring?事務(wù)的傳遞性的仪搔,默認(rèn)值為:required瘾婿,也就是如果有事務(wù),就加入事務(wù)烤咧,如果沒有偏陪,就創(chuàng)建事務(wù)。
這個(gè)參數(shù)的值有很多煮嫌,例如:REQUIRES_NEW笛谦,這個(gè)值就代表創(chuàng)建一個(gè)新的事務(wù),與原來的事務(wù)分開昌阿。
我們將剛剛那個(gè)方法修改一下:
@Service
publicclassServiceA{
@Transactional
publicvoiddoSomething(){
insert();
調(diào)用其他系統(tǒng);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
publicvoidinsert(){
向數(shù)據(jù)庫(kù)中添加數(shù)據(jù);
}
}
執(zhí)行之后饥脑,發(fā)現(xiàn)結(jié)果還是沒有改變,必須要整體執(zhí)行完成灶轰,數(shù)據(jù)庫(kù)中數(shù)據(jù)才會(huì)出現(xiàn)内地,說明還是在一個(gè)事務(wù)中。Spring的核心思想敞嗡,推薦你看看沃粗。
我們?cè)賹⒋a修改一下:
@Service
publicclassServiceA{
@Autowired
privateServiceB serviceB;
@Transactional
publicvoiddoSomething(){
serviceB.insert();
調(diào)用其他系統(tǒng);
}
}
@Service
publicclassServiceB{
@Transactional(propagation = Propagation.REQUIRES_NEW)
publicvoidinsert(){
向數(shù)據(jù)庫(kù)中添加數(shù)據(jù);
}
}
當(dāng)然Spring?其實(shí)也考慮這個(gè),在Spring?的配置中,我們只需要添加標(biāo)簽:
或者:
并且在代碼的調(diào)用中要求使用代理對(duì)象去調(diào)用即可:
((ServiceA)AopContext.currentProxy()).insert();
分享一套不錯(cuò)的架構(gòu)師學(xué)習(xí)參考資料师逸,免費(fèi)領(lǐng)取的动知,無(wú)任何套路奠滑!交流群:818491202 驗(yàn)證:88? 直接領(lǐng)取