版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
第五章事務管理查詢回顧Hibernate數(shù)據(jù)查詢HQLCriteria原生SQL查詢目標理解事務的概念及特性理解并應用事務隔離級別掌握Hibernate事務API掌握悲觀鎖和樂觀鎖的應用了解數(shù)據(jù)庫事務數(shù)據(jù)庫事務組合了數(shù)據(jù)庫訪問操作。一個事務要被確保以兩種方式終止:提交或回滾。為了在事務內(nèi)執(zhí)行所有的數(shù)據(jù)庫操作,必須標記這個工作單的范圍,必須啟用事務,在某個時間提交變化。如果出現(xiàn)錯識,必須回滾事務,保留數(shù)據(jù)的一致狀態(tài)。事務管理概述原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)一起稱為ACID標準。Atomicity:一個事務中包含的所有都是一個不可分割的工作單元。Consistency:只有合法的數(shù)據(jù)可以被寫入數(shù)據(jù)庫,如果有任何違例(比如數(shù)據(jù)與字段類型不符),事務應該將其回滾到最初狀態(tài)。Isolation:事務允許多個用戶對同一數(shù)據(jù)的并發(fā)訪問,而不破壞數(shù)據(jù)的正確性和完整性,同時并行事務的修改和其他并行事務的修改相互獨立。Durability:一旦事務被提交之后,處理結果被固化(保存到可掉電存儲器上)。數(shù)據(jù)庫并發(fā)問題臟讀(Dirtyread)–如果一個事務讀取另一個事務沒有提交的數(shù)據(jù)。數(shù)據(jù)庫并發(fā)問題不可重復讀(Unrepeatableread)–一個事務再次讀取之前曾讀取的數(shù)據(jù),兩次讀取結果不一樣。數(shù)據(jù)庫并發(fā)問題幻讀(Phantomread)–一個事務執(zhí)行一個查詢兩次,并且第二個結果集包括第一個結果集中不存在的記錄。不可重復讀和幻讀的區(qū)別,前者針對一條數(shù)據(jù),后者針對整張表數(shù)據(jù)庫并發(fā)問題兩類丟失更新:第一類丟失更新:一個事務的回滾將其他事務提交的數(shù)據(jù)覆蓋數(shù)據(jù)庫并發(fā)問題兩類丟失更新:第二類丟失更新:一個事務的提交將其他事務提交的數(shù)據(jù)覆蓋紅線之上的部分兩個線程執(zhí)行順序無所謂,那一刻兩個線程都查詢除了相同的一條記錄事務隔離級別(1)未提交讀(Readmitted)–允許臟讀取,但不允許丟失更新提交讀(Readcommitted)–不會讀到另一個并行事務已修改但未提交的數(shù)據(jù),避免“臟讀”,此隔離級別是大多數(shù)主流數(shù)據(jù)庫默認隔離級別,同時也適用于大多數(shù)應用系統(tǒng)??芍貜妥x(Repeatableread)–一個事務不可能更新已經(jīng)由另一個事務讀取但未提交的數(shù)據(jù),避免不可重復讀取和臟讀取串行讀(Serializable)–最嚴格的事務隔離,要求事務序列化執(zhí)行,事務只能一個接著一個地執(zhí)行,但不能并發(fā)執(zhí)行事務隔離級別(2)隔離級別臟讀不可重復讀幻讀第一類丟失更新第二類丟失更新Readmitted會會會不會會ReadCommitted不會會會不會會RepeatableRead不會不會會不會不會Serializable不會不會不會不會不會4種隔離級別嚴密程度又前往后依次遞增,同時其性能也依次下降,因此采取最高性能隔離級別并不可取,我們需根據(jù)實際情況進行取舍,以獲得數(shù)據(jù)合法性和系統(tǒng)性能上最佳平衡。
這4種隔離級別是SQL92定義的標準,但是具體數(shù)據(jù)庫不一定完全遵守這個標準,例如MYSQL5.x版本的InnoDBRead存儲引擎,RepeatableRead隔離級別仍然會發(fā)生第二類丟失更新選擇隔離級別首先排除”未提交讀”隔離級別絕大部分應用都無須使用“序列化”隔離(一般來說,讀取幻影數(shù)據(jù)并不是一個問題),此隔離級別也難以測量(scalepoorly)可重復讀隔離級別,消除一個事務在另外一個并發(fā)事務過程中覆蓋數(shù)據(jù)的可能性數(shù)據(jù)庫默認隔離級別數(shù)據(jù)庫默認隔離級別不是所有數(shù)據(jù)庫都支持事務,支持事務的數(shù)據(jù)庫也不一定支持所有隔離級別,可以通過Connection#getMetaData()方法活的DatabaseMetaData對象,再調(diào)用supportsTransactions()方法查看是否支持事務,調(diào)用supportsTransactionIsolationLevel(intlevel)來查看是否支持指定的隔離級別,level值見下一頁大多數(shù)數(shù)據(jù)庫的默認隔離級別為:ReadCommited,如SqlServer,Oracle.少數(shù)數(shù)據(jù)庫默認的隔離級別為RepeatableRead,如MySQLInnoDB存儲引擎設置隔離級別隔離級別值1–讀取未提交隔離2–讀取提交隔離
4–可重復讀隔離
8–串行讀隔離
Hibernate在配置文件中設置隔離級別Hibernate不會改變從應用服務器獲取的數(shù)據(jù)庫連接的隔離級別設置隔離級別—
配置文件設置隔離層次,控制事務的并發(fā),缺省時ReadCommitted:2<propertyname="hibernate.connection.isolation">2</property>Hibernate事務
Hibenrate是JDBC的輕量級封裝,本身并不具備事務管理能力,因此在事務管理層Hibernate將其委托給底層的JDBC或者JTA,以實現(xiàn)事務的管理與調(diào)度;底層事務實現(xiàn)方式定義在Hibernate配置文件中,Hibernate默認事務處理機制基于JDBCTransaction。事務實現(xiàn)方式—
配置文件<!--配置事務--><!--非管理環(huán)境:桌面應用,tomcat環(huán)境,可以不寫,縮寫是:jdbc
--><propertyname="transaction.factory_class"> org.hibernate.transaction.JDBCTransactionFactory</property><!--管理環(huán)境,JTA事務,縮寫是:jta--><!--propertyname="transaction.factory_class"> org.hibernate.transaction.JTATransactionFactory</property-->Hibernate事務—
基于JDBC實現(xiàn)Hibernate代碼片段:Sessions=sessionFactory.openSession();Transactiontx=s.beginTransaction();……mit();JDBC代碼片段:Connectionconn=DiverManager.getConnection();conn.setAutoCommit(false);……mit();Hibernate事務—
基于JTA實現(xiàn) JTA事務(分布式事務)是有JTAContainer維護的,事務的生命周期由JTAContainer維護,與具體Connection無關Hiberante事務APIpublicvoidtransientToPersist(){Sessionses=sf.openSession();Transactiontx=ses.beginTransaction();//創(chuàng)建一個transient對象cCoursec=newCourse("CoreC++","C++fundamental");try{ //將transient對象c變成了persistent對象c cid=(Long)ses.save(c); mit();}catch(HibernateExceptionhe){ tx.rollback(); throwhe;}finally{ses.close();} //persistent對象c變成了detached對象c}//garbagecollectionc提交回滾關閉調(diào)用mit()方法同步Session狀態(tài)到數(shù)據(jù)庫。如果s.save(c)拋出一個異常,則必須強制調(diào)用tx.rollback()方法回滾事務。非常重要的是,不管成功與否,都要在finally代碼塊關閉Session,以確保JDBC連接釋放到數(shù)據(jù)庫連接池。演示第二類丟失更新SQL92標準中規(guī)定RepeatableRead隔離級別能防止第二類丟失更新,我們驗證一下MYSQL5.1的隔離級別設置為4,驗證是否會出現(xiàn)第二類丟失更新:<property
name="hibernate.connection.isolation">4</property>演示第二類丟失更新
——源碼(1/2)第二類丟失更新出現(xiàn)的時機見之前的圖表:讓主線程和子線程都讀取到賬戶余額,1000元讓子線程先取出100元,提交讓主線程存入100元,提交@Testpublic
voidtest1()throwsInterruptedException{SessionoutSession=sessionFactory.openSession();TransactionoutTx=outSession.beginTransaction();//創(chuàng)建新線程newThread(){@Overridepublic
voidrun(){SessioninnerSession=sessionFactory.openSession();TransactioninnerTx=innerSession.beginTransaction();Queryquery=innerSession.createQuery("selectafromAccountawherea.id=1");System.out.println(Thread.currentThread().getName()+":新線程發(fā)起sql");AccountinnerAccount=(Account)query.uniqueResult();System.out.println(Thread.currentThread().getName()+":新線程讀取完數(shù)據(jù)");演示第二類丟失更新
——源碼(2/2)try{Thread.sleep(50);}catch(InterruptedExceptione){e.printStackTrace();}innerAccount.setBalance(innerAccount.getBalance()-100);mit();innerSession.close();}}.start();Thread.sleep(50);//讓子線程先執(zhí)行查詢System.out.println(Thread.currentThread().getName()+":主線程發(fā)起sql");AccountoutAccount=(Account)outSession.get(Account.class,1);System.out.println(Thread.currentThread().getName()+":主線程讀取完數(shù)據(jù)");Thread.sleep(100);outAccount.setBalance(outAccount.getBalance()+100);mit();outSession.close();}演示第二類丟失更新
——結果是賬戶余額為110元,出現(xiàn)了第二類丟失更新,當把隔離級別設置為8時,問題解決了,主線程后更新數(shù)據(jù)時會拋出異常:org.hibernate.exception.LockAcquisitionException:couldnotexecutestatement說明mysql的事務隔離級別為RepeatableRead時,仍然會出現(xiàn)第二類丟失更新,其他數(shù)據(jù)庫可以同理驗證如何不犧牲效率選擇Serializable隔離級別,又能解決第二類丟失更新呢?答案是使用鎖鎖(locking)業(yè)務邏輯處理中,往往需要數(shù)據(jù)訪問排他性,需要通過一些機制保證這個數(shù)據(jù)在操作過程中不會被外界修改,鎖是預防在并發(fā)訪問數(shù)據(jù)資源時,當一個事務對數(shù)據(jù)加鎖后,沒有并發(fā)事務能讀或者修改該數(shù)據(jù)資源。悲觀鎖(PessimisticLocking)樂觀鎖(OptimisticLocking)悲觀鎖悲觀鎖在讀取數(shù)據(jù)資源進行加鎖,直到事務完成該鎖被釋放掉。依賴數(shù)據(jù)庫的悲觀鎖(forupdate)select*fromt_userwherename=‘zz’forupdate悲觀鎖鎖模式Hibernate內(nèi)部鎖機制(LockOptions和LockMode中都提供了,功能有重復的):LockOptions.NONE–無鎖機制LockMode.WRITE–Hibernate在Insert和Update記錄時會自動獲取LockOptions.READ–Hibernate讀取記錄時會自動獲取數(shù)據(jù)庫鎖機制:LockOptions.UPGRADE–利用數(shù)據(jù)庫的forupdate子句加鎖LockMode.
PESSIMISTIC_WRITE—功能與上同LockMode.UPGRADE_NOWAIT–Oracle的特定實現(xiàn),利用oracle的forupdatenowait子句實現(xiàn)加鎖盡管hibernate文檔,源碼注釋都這如上所說,但是經(jīng)過驗證,除了UPGRADE和PESSIMISTIC_WRITE之外,其他說法不可靠或不正確,我們只關注這兩個就可以了。悲觀鎖使用方式悲觀鎖有三種使用方式:Session上設置HQL檢索時設置Criteria檢索是設置原生SQL檢索不支持悲觀鎖的設置,但是SQL中可以嵌入forupdate悲觀鎖使用方式Session上設置分為兩種:對持久化狀態(tài)的實體對象加悲觀鎖檢索之前對Session加悲觀鎖//這種方式在加悲觀鎖時會單獨發(fā)起一條sql,不推薦使用,因為發(fā)起加鎖的sql//持久化狀態(tài)的實體對象屬性可能已經(jīng)變了,加鎖失去了意義。Accountaccount=(Account)session.get(Account.class,1);session.buildLockRequest(LockOptions.UPGRADE).lock(account);//這種方式在查詢時就加了悲觀鎖,少發(fā)送一條sql,而且不會出現(xiàn)第一種//的情況,建議使用這種方式Accountaccount=(Account)session.get(Account.class,1,LockOptions.UPGRADE);悲觀鎖使用方式HQL檢索時的悲觀鎖設置:Criteria檢索時的悲觀鎖設置:Accountaccount=(Account)session.createQuery("selectafromAccountawherea.id=1").setLockOptions(LockOptions.UPGRADE).uniqueResult();Accountaccount=(Account)session.createCriteria(Account.class) .add(Restrictions.eq("id",1)) .setLockMode(LockMode.PESSIMISTIC_WRITE) .uniqueResult();悲觀鎖的問題點依賴數(shù)據(jù)庫的selectforupdate實現(xiàn),對數(shù)據(jù)安全要求很高的情況使用,效率比較低數(shù)據(jù)數(shù)據(jù)庫并發(fā)修改一條數(shù)據(jù)的幾率很低,用悲觀鎖就不合適了,可以使用樂觀鎖樂觀鎖Hibernate使用樂觀版本管理可以使第二和每三個策略生效實現(xiàn)方式:version:版本機制(版本號或時間戳)版本機制版本管理使用一個增長的版本號或一個當前時間的時間戳操作員A此時讀出數(shù)據(jù)(version=1),并從賬戶扣除余額在A操作過程中,B也讀入此用戶信息(version=1),并扣除余額A修改完成之后,增加版本號(version=2),并更新余額信息B修改完成后,增加版本號(version=2
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024河北省職稱計算機考試操作題步驟
- 《物質生活與習俗的變遷》課件
- 《激光的基本特性》課件
- 《證券投資學課程》課件
- 《電器安全知識》課件
- 農(nóng)業(yè)新紀元模板
- 銀行工作總結辛勤勞動取得佳績
- 三年級安全教育行動
- 法制教育心得體會15篇
- 輸血科護士工作總結
- 火力發(fā)電廠有關職業(yè)病的危害及防護
- 民主測評票(三種樣式)
- 班車安全檢查表(2015-7-14)V3 0 (2)
- 城投集團年度安全管理工作計劃
- 一、 行業(yè)協(xié)會申請設立分支機構、代表機構應提交的文件:
- 幼兒園幼兒園理事會成員一覽表
- 學生對課堂教學滿意度調(diào)查
- 住房公積金中心窗口人員個人工作總結
- 集成電路單粒子效應評估技術研究PPT課件
- 幼兒園小班生成活動教案20篇
- 講師與平臺的合作協(xié)議
評論
0/150
提交評論