這篇文章將為大家詳細(xì)講解有關(guān)悲觀鎖與樂觀鎖怎么利用Hibernate實(shí)現(xiàn),文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。
創(chuàng)新互聯(lián)公司是一家從事企業(yè)網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、行業(yè)門戶網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)制作的專業(yè)網(wǎng)絡(luò)公司,擁有經(jīng)驗(yàn)豐富的網(wǎng)站建設(shè)工程師和網(wǎng)頁設(shè)計(jì)人員,具備各種規(guī)模與類型網(wǎng)站建設(shè)的實(shí)力,在網(wǎng)站建設(shè)領(lǐng)域樹立了自己獨(dú)特的設(shè)計(jì)風(fēng)格。自公司成立以來曾獨(dú)立設(shè)計(jì)制作的站點(diǎn)上千余家。
四種隔離機(jī)制不要忘記:(1,2,4,8)
1.read-uncommitted:能夠去讀那些沒有提交的數(shù)據(jù)(允許臟讀的存在)
2.read-committed:不會出現(xiàn)臟讀,因?yàn)橹挥辛硪粋€事務(wù)提交才會讀取來結(jié)果,但仍然會出現(xiàn)不可重復(fù)讀和幻讀現(xiàn)象。
4.repeatable read:MySQL 默認(rèn)??芍貜?fù)讀,讀數(shù)據(jù)讀出來之后給它加把鎖,其他人先別更新,等我用完了你再更新。你的事務(wù)沒完,其他事務(wù)就不可能改這條記錄。
8.serializable:序列化,最高級別。一個一個來,不去并發(fā)。效率最低。
hibernate的隔離機(jī)制
i.hibernate.connection.isolation=2
ii.用悲觀鎖解決:repeatable read的問題(依賴于數(shù)據(jù)庫的鎖)
a)LockMode.None 無鎖的機(jī)制,Transaction結(jié)束時,切換到此模式
b)LockMode.read 在查詢的時候 hibernate會自動獲取鎖
c)LockMode.write insert update hibernate會自動獲取鎖
d)以上3中鎖的模式,是hibernate內(nèi)部使用的
e)LockMode.UPGRADE_NOWAIT ORACLE支持的鎖的方式
例子:
Account.java:
package com.bjsxt.hibernate; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Account { private int id; private int balance; //BigDecimal @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public int getBalance() { return balance; } public void setBalance(int balance) { this.balance = balance; } }
hibernate.cfg.xml中配置:
測試:
@Test public void testSave() { Session session = sf.openSession(); session.beginTransaction(); Account a = new Account(); a.setBalance(100); session.save(a); session.getTransaction().commit(); session.close(); } @Test public void testOperation1() { Session session = sf.openSession(); session.beginTransaction(); Account a = (Account)session.load(Account.class, 1); int balance = a.getBalance(); //do some caculations balance = balance - 10; //在保存時很有可能會把在同一時期修改的給覆蓋掉 //這個時候上一把"鎖"就可以避免這個問題 a.setBalance(balance); session.getTransaction().commit(); session.close(); } //下面這個就是對上面那個例子做的修改 @Test public void testPessimisticLock() { Session session = sf.openSession(); session.beginTransaction(); //給它加把鎖,加鎖的機(jī)制上面已經(jīng)提到了 Account a = (Account)session.load(Account.class, 1, LockMode.UPGRADE); int balance = a.getBalance(); //do some caculation balance = balance - 10; a.setBalance(balance); session.getTransaction().commit(); session.close(); }
這是依賴于數(shù)據(jù)庫的鎖的,也就是給數(shù)據(jù)庫一個指令,要求數(shù)據(jù)庫幫忙加鎖。
——————————————————————————————————————
iii.Hibernate(JPA)樂觀鎖定(ReadCommitted)
這不是依賴數(shù)據(jù)庫加鎖的,是在程序中加鎖的。
舉個例子:一個數(shù)據(jù)需要隔離機(jī)制(不能重復(fù)讀),這個時候在更新的字段上加"版本號"(version字段),一旦有人給它update一下,這個值就加1(version+1)。
那么這種機(jī)制是如何產(chǎn)生隔離能力的呢?
原因是事務(wù)A讀取字段的同時,事務(wù)B緊接著也讀取這個字段,而且改了它,此時version變成1了。這個時候事務(wù)A就會檢查字段是否被改變了,如果被改變它也做相應(yīng)的改變,沒有改變就不改。
樂觀鎖的實(shí)現(xiàn):(@Version)
Account.java:
package com.bjsxt.hibernate; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Version; @Entity public class Account { private int id; private int balance; private int version; @Version//加了這個注解就說明這個是專門用來做版本標(biāo)注的 public int getVersion() { return version; } public void setVersion(int version) { this.version = version; } @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public int getBalance() { return balance; } public void setBalance(int balance) { this.balance = balance; } }
測試:
@Test public void testSave() { Session session = sf.openSession(); session.beginTransaction(); Account a = new Account(); a.setBalance(100); session.save(a); session.getTransaction().commit(); session.close(); } @Test public void testOptimisticLock() { Session session = sf.openSession(); Session session2 = sf.openSession(); session.beginTransaction(); Account a1 = (Account) session.load(Account.class, 1); session2.beginTransaction(); Account a2 = (Account) session2.load(Account.class, 1); a1.setBalance(900); a2.setBalance(1100); //第一個session一旦提交,version就會+1 session.getTransaction().commit(); System.out.println(a1.getVersion()); //第二個session提交的時候,一看version不一樣就會報(bào)錯 //出了錯誤做個記錄,下次再提交(也可以用其他方法) session2.getTransaction().commit(); System.out.println(a2.getVersion()); session.close(); session2.close(); }
關(guān)于悲觀鎖與樂觀鎖怎么利用Hibernate實(shí)現(xiàn)就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。