基于Spring JDBC的事務(wù)處理
事務(wù)(Transaction):在數(shù)據(jù)庫中,可以保持一系列的數(shù)據(jù)操作要么全部執(zhí)行成功,要么全部執(zhí)行失敗的機(jī)制!
假設(shè)存在以下信息:
如果存在任務(wù)“王五向阿三轉(zhuǎn)賬5000元”,需要執(zhí)行的SQL語句大致是:
update 賬戶信息表 set 余額=余額-5000 where 賬戶='王五';
update 賬戶信息表 set 余額=余額+5000 where 賬戶='阿三';
如果出現(xiàn)某種意外,導(dǎo)致以上第1條SQL語句成功執(zhí)行了,第2條卻無法執(zhí)行或執(zhí)行失敗,就會(huì)出現(xiàn)數(shù)據(jù)安全問題(當(dāng)然,把以上2條SQL語句的執(zhí)行順序?qū)φ{(diào)后,出現(xiàn)以上狀態(tài)也是不安全的),。
在以上這種“轉(zhuǎn)賬”的任務(wù)中,如果2條SQL語句都執(zhí)行成功,就是預(yù)期的效果,但是,即使是2條SQL語句都執(zhí)行失敗了,數(shù)據(jù)安全也不會(huì)受到影響,也屬于是可以接受的,。
在基于Spring JDBC的編程中,只需要為業(yè)務(wù)方法加上@Transactional
注解,就可以使得該業(yè)務(wù)方法中的多條數(shù)據(jù)操作是有事務(wù)的保障的,這多條數(shù)據(jù)操作要么全部成功,要么全部失敗,不會(huì)出現(xiàn)成功一半且失敗一半的問題!
框架在處理“事務(wù)”時(shí),其大致的執(zhí)行方式是:
try {
開啟事務(wù)(BEGIN)
執(zhí)行一系列的數(shù)據(jù)操作
提交事務(wù)(COMMIT)
} catch (RuntimeException e) {
回滾事務(wù)(ROLLBACK)
}
所以,在基于Spring JDBC的編程中,需要注意:
- 如果某個(gè)業(yè)務(wù)涉及2次或2次以上的增刪改(例如2次
UPDATE
操作,或1次INSERT
與1次DELETE
,或其它)操作,必須在業(yè)務(wù)方法的聲明之前添加@Transactional
注解,以使得該業(yè)務(wù)的執(zhí)行過程中是有事務(wù)的保障的; - 在調(diào)用持久層的增刪改操作時(shí),必須及時(shí)獲取返回的受影響行數(shù),并判斷受影響行數(shù)是否是預(yù)期值,如果不是,必須拋出
RuntimeException
或其子孫類異常!
另外,@Transactional
注解還可以添加在業(yè)務(wù)類的聲明之前,則當(dāng)前業(yè)務(wù)類中所有業(yè)務(wù)方法都是有事務(wù)保障的,但是,通常沒有這個(gè)必要性,所以,并不推薦這樣使用!
課后,可自行了解:事務(wù)的ACID特性,事務(wù)的傳播,事務(wù)的隔離。