聲明:本欄目所使用的素材都是凱哥學(xué)堂VIP學(xué)員所寫,學(xué)員有權(quán)匿名,對(duì)文章有最終解釋權(quán);凱哥學(xué)堂旨在促進(jìn)VIP學(xué)員互相學(xué)習(xí)的基礎(chǔ)上公開筆記。
事務(wù)與鎖是關(guān)聯(lián)在一起的,事務(wù)->鎖
早期數(shù)據(jù)庫是單機(jī)版居多,不存在訪問量很大和多人同時(shí)訪問的情況,因此數(shù)據(jù)安全性比較高。在現(xiàn)在的網(wǎng)絡(luò)型數(shù)據(jù)庫大行的時(shí)代,往往會(huì)出現(xiàn)同時(shí)訪問的情況,這種會(huì)對(duì)數(shù)據(jù)安全性產(chǎn)生隱患。
寫業(yè)務(wù)代碼操作數(shù)據(jù)庫中數(shù)據(jù)的時(shí)候,不僅僅是一條兩條SQL語句的,很多條SQL語句需要按順序來訪問數(shù)據(jù)庫: 比如寫一個(gè)購買商品的業(yè)務(wù):
1.添加一條數(shù)據(jù)進(jìn)入訂單表
2.減少商品庫存
3.增加一條購買數(shù)據(jù)
4.增加一條物流需求
5.寫日志數(shù)據(jù)庫
或者是學(xué)生退學(xué)業(yè)務(wù):
1.將學(xué)生表的學(xué)生信息狀態(tài)改為退學(xué)
2.將學(xué)生卡狀態(tài)改為暫停
3.增加一條學(xué)生的金額退還記 錄 4.刪除學(xué)生日常信息
5.添加學(xué)生退學(xué)記錄
可見業(yè)務(wù)代碼中需要執(zhí)行的SQL語句是很多的,這么多SQL語句的執(zhí)行只是為了完成一個(gè)業(yè)務(wù)。
這么多SQL語句,如果其中的一條SQL語句執(zhí)行失敗了,則這整個(gè)業(yè)務(wù)就是失敗的了。
比如,如果第三條SQL執(zhí)行失敗了,但是第一、二條SQL語句還是執(zhí)行成功了的,而第四、五條記錄則執(zhí)行失敗,這樣子的話,數(shù)據(jù)庫中的數(shù)據(jù)就不是完整的了。 也就是說,我們的業(yè)務(wù)代碼的SQL語句寫出來,不一定是它們就能順利執(zhí)行、不一定就能保證它們能夠符合業(yè)務(wù)邏輯需求,在沒有接觸到事務(wù)之前,這些是無法保證的。
那么事務(wù)就是用來保證如上面的那5條SQL語句能夠順利執(zhí)行,能夠按照你的邏輯全部正常通過。
我們寫業(yè)務(wù)代碼的時(shí)候,涉及到很多條SQL語句,如果我們寫了20條SQL語句,但是第10條SQL語句執(zhí)行不通過或者不符合業(yè)務(wù)邏輯需求,我們需要回到最開始再去從頭開始執(zhí)行SQL語句,前面執(zhí)行了的十條SQL語句作廢,這種回到最開頭的情況叫做回滾。如果你不回滾,接著把不通過SQL語句后面的語句繼續(xù)執(zhí)行的話,就會(huì)發(fā)生數(shù)據(jù)不一致的情況了。數(shù)據(jù)不完整、不同步了。會(huì)導(dǎo)致系統(tǒng)數(shù)據(jù)不健全。
事務(wù)就是用來確保所有SQL語句順利執(zhí)行,這里的順利執(zhí)行,并不僅僅是指不會(huì)報(bào)錯(cuò),而是這個(gè)SQL語句是按照你的業(yè)務(wù)邏輯來執(zhí)行,就算一條SQL語句不報(bào)錯(cuò),但是沒有按照業(yè)務(wù)邏輯的話,也可以讓它前面的所有SQL語句作廢,進(jìn)行回滾。當(dāng)所有的SQL語句全部按照你的業(yè)務(wù)邏輯意思順利執(zhí)行后,就可以把它寫入到數(shù)據(jù)庫中去永久執(zhí)行。
事務(wù)不可分割,不可以一分為二來執(zhí)行。
事務(wù):
1.提交:如果你覺得所有的SQL語句執(zhí)行都是正確的,你可以調(diào)用提交,永久的寫入到數(shù)據(jù)庫、永久保存
2.回滾:在執(zhí)行SQL語句過程中,發(fā)生任何問題,都可以回滾、取消前面執(zhí)行的所有SQL語句,回到初始狀態(tài)。
今后業(yè)務(wù)涉及到的很多的SQL語句,在把所有的SQL語句發(fā)送到數(shù)據(jù)庫中去操作數(shù)據(jù)之前,先建立一個(gè)事務(wù),在事務(wù)里面一條一條的執(zhí)行所有需要的SQL語句,執(zhí)行完了之后,你在決定到底是提交還是回滾。提交,則所有的SQL語句會(huì)全部寫入數(shù)據(jù)庫中保存、執(zhí)行?;貪L,則會(huì)前面所有執(zhí)行的SQL語句全部取消,事務(wù)保證整個(gè)業(yè)務(wù)的完整執(zhí)行、確保了數(shù)據(jù)的一致性。
跨行取錢:本行取錢的時(shí)候是本行系統(tǒng),在最開始登陸的時(shí)候會(huì)調(diào)用本系統(tǒng)的驗(yàn)證模塊來驗(yàn)證賬戶密碼,但是跨行取錢的時(shí)候,不是使用的本行系統(tǒng),所以最開始登陸的時(shí)候不調(diào)用別行的系統(tǒng)來驗(yàn)證,而是等你登陸進(jìn)去后,選好了取款、查詢等操作后,再一起把需要進(jìn)行的驗(yàn)證、操作內(nèi)容等SQL發(fā)送到別行系統(tǒng)上去執(zhí)行。所以跨行取錢的時(shí)候,你輸入任何密碼都會(huì)登陸進(jìn)去。
取錢時(shí)涉及的事務(wù):當(dāng)你取200元的時(shí)候,用戶同意取錢,會(huì)在數(shù)據(jù)庫中減去200+2元,然后準(zhǔn)備給你出鈔票,如果此時(shí)ATM突然掉電而沒有拿出錢,這里系統(tǒng)會(huì)回滾,會(huì)讓數(shù)據(jù)庫中數(shù)據(jù)回到未扣款時(shí)的狀態(tài),也就是會(huì)把200+2給你加回去。這樣能保證這個(gè)業(yè)務(wù)的完整執(zhí)行和數(shù)據(jù)的安全性、完整性。
事務(wù)不是屬于JDBC的技術(shù),是數(shù)據(jù)庫本身的一種機(jī)制、特性,但是JDBC可以控制事務(wù),可以控制事務(wù)的開始、回滾、提交等。事務(wù)的結(jié)束有兩種要么回滾要么提交。
JDBC中事務(wù)有兩種模式1.自動(dòng)事務(wù)(默認(rèn))2.手動(dòng)事務(wù)(自己一定要提交或者回滾來結(jié)束事務(wù))。
自動(dòng)事務(wù):只要你的SQL語句正確執(zhí)行就會(huì)提交,不管你的SQL語句的執(zhí)行結(jié)果是否是業(yè)務(wù)邏輯所需要的,都會(huì)提交。
學(xué)了事務(wù)之后,就一定使用事務(wù)。
JDBC中的事務(wù)在Connection接口下管理,設(shè)置事務(wù)模式的方法是setAutoCommit(),參數(shù)可以是true或者false,true的話表示自動(dòng)提交式事務(wù)管理,false表示手動(dòng)提交式事務(wù)管理。默認(rèn)是true。
在手動(dòng)式提交事務(wù)管理中有兩個(gè)方法,commit和rollback,這兩個(gè)方法是用來提交和回滾的。手動(dòng)情況下,要自己親自調(diào)用這兩個(gè)方法。
當(dāng)選擇手動(dòng)提交事務(wù)模式的時(shí)候,如果最后的時(shí)候沒有提交或者回滾,會(huì)默認(rèn)回滾。
這里使用Statement來執(zhí)行SQL語句,設(shè)置為手動(dòng)提交模式,但是最后沒有提交也沒有回滾,此時(shí)會(huì)自動(dòng)回滾,所以數(shù)據(jù)庫中數(shù)據(jù)還在。
當(dāng)你調(diào)用的一個(gè)事務(wù)結(jié)束之后(rollback或者commit),新的事務(wù)又可以開始使用了。
這里一個(gè)連接中有兩條SQL語句,有一個(gè)事務(wù),兩條SQL語句st和pst,等兩個(gè)SQL語句執(zhí)行完后,一起提交。
而上面這種情況是有兩個(gè)事務(wù),第一個(gè)事務(wù)st執(zhí)行完后,手動(dòng)提交了,然后數(shù)據(jù)庫中的數(shù)據(jù)刪除了,然后執(zhí)行第二個(gè)事務(wù),第二個(gè)事務(wù)沒有提交也沒有回滾,則默認(rèn)回滾,所以顯示數(shù)組里都是1,表示插入執(zhí)行了,但是因?yàn)樽詈笥只貪L了,回滾到了事務(wù)最開始時(shí),數(shù)據(jù)庫中沒有數(shù)據(jù)的狀態(tài),所以數(shù)據(jù)庫中仍然沒有數(shù)據(jù)。
把模式改為自動(dòng)提交模式,最后一個(gè)事務(wù)里的兩條SQL語句都會(huì)默認(rèn)提交。
這種情況,最開始把事務(wù)設(shè)置為自動(dòng)模式,第一個(gè)SQL語句執(zhí)行,把數(shù)據(jù)庫中的所有數(shù)據(jù)刪除了,然后等待執(zhí)行第二個(gè)SQL語句,并且在執(zhí)行第二個(gè)SQL語句前把模式改為手動(dòng)了。執(zhí)行完第二條SQL語句后,往數(shù)據(jù)庫中插入了10條數(shù)據(jù),這樣兩條SQL語句算是執(zhí)行完了,然后在決定這兩條SQL語句是提交還是回滾了,因?yàn)閳?zhí)行完第二條SQL語句后,模式是手動(dòng)的了,因?yàn)闆]有寫明是提交還是回滾,就默認(rèn)回滾了,就會(huì)回滾到第二條SQL語句沒有執(zhí)行前的哪種狀態(tài),也就是數(shù)據(jù)沒有的狀態(tài)。
需注意,如果你把模式設(shè)置為自動(dòng)模式的話,就不能在手動(dòng)的去調(diào)用conn.rollback或者conn.commit了,不然會(huì)報(bào)錯(cuò)。
這種情況下,有兩個(gè)事務(wù),第一個(gè)事務(wù)是手動(dòng)模式,st執(zhí)行完SQL語句后,手動(dòng)提交了,所以數(shù)據(jù)刪除了,第二個(gè)事務(wù)是自動(dòng)模式,pst執(zhí)行完后,會(huì)自動(dòng)提交,所以又添加進(jìn)來10行數(shù)據(jù),最后結(jié)果還是10行數(shù)據(jù)。
這種情況最開始是5條數(shù)據(jù),往里面插入數(shù)據(jù),開始設(shè)置事務(wù)為自動(dòng)模式,執(zhí)行第一條SQL語句,插入一條數(shù)據(jù),然后在執(zhí)行第二條SQL語句前把事務(wù)模式改為手動(dòng)模式,再插入另外一條SQL語句,兩條SQL語句完成了之后,一起決定這兩條SQL語句是提交還是回滾的時(shí)候,手動(dòng)模式,因?yàn)闆]有顯示聲明,所以默認(rèn)回滾了,回滾到第二條SQL語句開始執(zhí)行前的狀態(tài),所以數(shù)據(jù)庫中只會(huì)【學(xué)Java,到凱哥學(xué)堂kaige123.com】插入第一條數(shù)據(jù),但是實(shí)際上第二條數(shù)據(jù)也插入過的,不過回滾的時(shí)候又把它刪除了,看uid從348->350,可以知道中間空了一個(gè)349,就是第二條插入后又被刪除了的那個(gè)。