事務(wù)的含義:
事務(wù)可以看作是由對(duì)數(shù)據(jù)庫(kù)的若干操作組成的一個(gè)單元唉铜,這些操作要么都完成,要么都取消,從而保證數(shù)據(jù)滿足一致性的要求浙巫。
事務(wù)的一個(gè)典型例子是銀行中的轉(zhuǎn)帳操作,帳戶A把一定數(shù)量的款項(xiàng)轉(zhuǎn)到帳戶B上刷后,這個(gè)操作包括兩個(gè)步驟的畴,一個(gè)是從帳戶A上把存款減去一定數(shù)量,二是在帳戶B上把存款加上相同的數(shù)量尝胆。這兩個(gè)步驟顯然要么都完成丧裁,要么都取消,否則銀行就會(huì)受損失含衔。顯然煎娇,這個(gè)轉(zhuǎn)帳操作中的兩個(gè)步驟就構(gòu)成一個(gè)事務(wù)。
事務(wù)的四個(gè)特征(ACID)
1.原子性(Atomicity):指事務(wù)中的操作抱慌,或者都完成逊桦,或者都取消。
2.一致性(Consistency):指事務(wù)中的操作保證數(shù)據(jù)庫(kù)中的數(shù)據(jù)不會(huì)出現(xiàn)邏輯上不一致的情況抑进,一致性一般會(huì)隱含的包括在其他屬性之中强经。
3.隔離性(Isolation):指當(dāng)前的事務(wù)與其他未完成的事務(wù)是隔離的。在不同的隔離級(jí)別下寺渗,事務(wù)的讀取操作匿情,得到的結(jié)果可能是不同的。
4.持久性(Durability):指對(duì)事務(wù)發(fā)出COMMIT命令后信殊,即使這時(shí)發(fā)生系統(tǒng)故障炬称,事務(wù)的結(jié)果也被持久化了。與此相反的是涡拘,當(dāng)在事務(wù)執(zhí)行過(guò)程中玲躯,系統(tǒng)發(fā)生故障時(shí),則事務(wù)的操作都被回滾,即數(shù)據(jù)庫(kù)回到事務(wù)開(kāi)始之前的狀態(tài)跷车。
如果沒(méi)有采取必要的隔離機(jī)制, 就會(huì)導(dǎo)致各種并發(fā)問(wèn)題:
1.更新丟失:
本來(lái)是:
1000-200=800
800-300=500
1000更新為500
錯(cuò)誤:
1000-200=800
1000-300=700
1000更新為700
2.臟數(shù)據(jù):
1000元更新為800元棘利,最后更新為500元⌒嘟桑可是讀取到的是中間的800元善玫。
3.不可重復(fù)讀
第一次讀取的數(shù)據(jù)和第二次讀取的數(shù)據(jù)不一致
4.幻讀:
第一次讀取到了3行數(shù)據(jù),然后有人刪除了1行數(shù)據(jù)密强,讀取到的數(shù)據(jù)變成了2行茅郎。
數(shù)據(jù)庫(kù)系統(tǒng)必須具有隔離并發(fā)運(yùn)行各個(gè)事務(wù)的能力, 使它們不會(huì)相互影響, 避免各種并發(fā)問(wèn)題。
不同隔離級(jí)別對(duì)應(yīng)不同的干擾程度, 隔離級(jí)別越高, 數(shù)據(jù)一致性就越好, 但并發(fā)性越弱或渤。
ANSI SQL標(biāo)準(zhǔn)定義了 4 種事務(wù)隔離級(jí)別:
SQL Server支持4中事務(wù)隔離級(jí)別系冗,默認(rèn)級(jí)別為: READ COMMITTED
盡管讓程序自主管理 Session 對(duì)象的生命周期也是可行的, 但是在實(shí)際Java應(yīng)用中, 把管理Session對(duì)象的生命周期交給 Hibernate管理, 可以簡(jiǎn)化Java應(yīng)用程序代碼和軟件架構(gòu)。
Hibernate提供了三種管理 Session 對(duì)象的方法:
1.Session對(duì)象的生命周期與本地線程綁定(我們學(xué)的)
記得配置cfg:<property name="current_session_context_class">thread</property>
2.Session對(duì)象的生命周期與JTA事務(wù)綁定
3.Hibernate委托程序管理Session對(duì)象的生命周期
在 Hibernate的配置文件中, current_session_context_class屬性用于指定Session管理方式, 可選值包括:
thread: Session對(duì)象的生命周期與本地線程綁定
jta: Session對(duì)象的生命周期與JTA事務(wù)綁定
managed: Hibernate委托程序來(lái)管理Session對(duì)象的生命周期
安全:一個(gè)線程劳坑,一個(gè)session
當(dāng)配置為thread時(shí)毕谴,SessionFactory的getCurrentSession()方法才能使用
當(dāng)一個(gè)線程(threadA)第一次調(diào)用 SessionFactory 對(duì)象的getCurrentSession() 方法時(shí), 該方法會(huì)創(chuàng)建一個(gè)新的Session(sessionA) 對(duì)象, 把該對(duì)象與threadA綁定, 并將sessionA返回
當(dāng)threadA再次調(diào)用SessionFactory對(duì)象的 getCurrentSession()方法時(shí), 該方法將返回sessionA對(duì)象
當(dāng)threadA提交sessionA對(duì)象關(guān)聯(lián)的事務(wù)時(shí),Hibernate會(huì)自動(dòng)清理sessionA對(duì)象的緩存, 然后提交事務(wù), 關(guān)閉sessionA對(duì)象。 當(dāng)threadA撤銷sessionA對(duì)象關(guān)聯(lián)的事務(wù)時(shí), 也會(huì)自動(dòng)關(guān)閉sessionA對(duì)象(也就是使用getCurrentSession() 獲取session不需要自行關(guān)閉)
若threadA再次調(diào)用SessionFactory對(duì)象的getCurrentSession()方法時(shí), 該方法會(huì)又創(chuàng)建一個(gè)新的 Session(sessionB)對(duì)象, 把該對(duì)象與threadA綁定, 并將sessionB返回
可以不用getCurrentSession()方法距芬,用ThreadLocal實(shí)現(xiàn)(jdk提供的)
ThreadLocal為解決多線程程序的并發(fā)問(wèn)題提供了一種新的思路涝开,ThreadLocal并不是一個(gè)Thread,而是Thread的局部變量框仔。
注意:獲取session需要自行關(guān)閉舀武。
s_h例子
對(duì)于WEB應(yīng)用,一個(gè)請(qǐng)求可能需要多次操作數(shù)據(jù)庫(kù)并返回?cái)?shù)據(jù)至JSP中進(jìn)行顯示离斩,可能有以上兩個(gè)問(wèn)題要考慮:
1.多次操作數(shù)據(jù)庫(kù)如何共享一個(gè)事務(wù)银舱?
2.對(duì)于懶加載的實(shí)體類,返回到JSP頁(yè)面時(shí)若session已關(guān)閉跛梗,那么就取不到這個(gè)實(shí)體的數(shù)據(jù)了寻馏,如何處理這類問(wèn)題?
說(shuō)明:事務(wù)從Service層開(kāi)始核偿,要取數(shù)據(jù)的時(shí)候诚欠,session關(guān)閉了,進(jìn)行不了以下過(guò)程漾岳。
闡述Session加載實(shí)體對(duì)象的過(guò)程:
① Session在調(diào)用數(shù)據(jù)庫(kù)查詢功能之前轰绵,首先會(huì)在一級(jí)緩存中通過(guò)實(shí)體類型和主鍵進(jìn)行查找,如果一級(jí)緩存查找命中且數(shù)據(jù)狀態(tài)合法尼荆,則直接返回左腔;
② 如果一級(jí)緩存沒(méi)有命中,接下來(lái)Session會(huì)在當(dāng)前NonExists記錄(相當(dāng)于一個(gè)查詢黑名單捅儒,如果出現(xiàn)重復(fù)的無(wú)效查詢可以迅速做出判斷液样,從而提升性能)中進(jìn)行查找振亮,如果NonExists中存在同樣的查詢條件,則返回null蓄愁;
③ 如果一級(jí)緩存查詢失敗則查詢二級(jí)緩存双炕,如果二級(jí)緩存命中則直接返回;
④ 如果之前的查詢都未命中撮抓,則發(fā)出SQL語(yǔ)句,如果查詢未發(fā)現(xiàn)對(duì)應(yīng)記錄則將此次查詢添加到Session的NonExists中加以記錄摇锋,并返回null丹拯;
⑤ 根據(jù)映射配置和SQL語(yǔ)句得到ResultSet,并創(chuàng)建對(duì)應(yīng)的實(shí)體對(duì)象荸恕;
⑥ 將對(duì)象納入Session(一級(jí)緩存)的管理乖酬;
⑦ 如果有對(duì)應(yīng)的攔截器,則執(zhí)行攔截器的onLoad方法融求;
⑧ 如果開(kāi)啟并設(shè)置了要使用二級(jí)緩存咬像,則將數(shù)據(jù)對(duì)象納入二級(jí)緩存;
⑨ 返回?cái)?shù)據(jù)對(duì)象生宛。
Action用到 Service
Service 用到 DAO
過(guò)濾器 用到 HibernateUtil 和 HibernateSessionFactory