Hibernate步步為營 鎖機制詳解

2021-06-22 11:06:26 字數 3732 閱讀 5192

上篇文章詳細討論了hql的各種查詢方法,在討論過程中寫了**示例,hql的查詢方法類似於sql,查詢的方法比較簡單,有sql基礎的開發人員在使用hql時就會變得相當的簡單。hibernate在運算元據庫的同時也提供了對資料庫操作的限制方法,這種方法被稱為鎖機制,hibernate提供的鎖分為兩種一種是樂觀鎖,另外一種是悲觀鎖。通過使用鎖能夠控制資料庫的併發性操作,限制使用者對資料庫的併發性的操作。

鎖能控制資料庫的併發操作,通過使用鎖來控制資料庫的併發操作,hibernate提供了兩種鎖來控制資料庫的操作,分別是樂觀鎖和悲觀鎖。

樂觀鎖:大多數是採用資料版本的方式實現,一般在資料庫中加入乙個version欄位,在讀取資料的時候將version取出來,在儲存資料的時候判斷version的值是否小於資料庫中的version值,如果小於不會更新,否則可更新資料庫。

悲觀鎖:通常是由資料庫機制實現的,在整個過程中把資料鎖住(查詢時),只要事務不釋放(提交/回滾)那麼任何使用者都不能檢視和修改,通過使用lockmode來控制對資料庫的操作。

樂觀鎖是通過在資料庫中新增乙個名為version的字段來實現每次對資料的校驗,在每次運算元據庫的時候會自動更新version的值,這樣每次操作的version值是不一樣的,所以如果有併發操作時將會首先校驗version值是否小於資料庫的version值,如果小於的話不會更新資料庫,它的具體使用方法如下示例:

該類是對映的實體類,其中的屬性quantity是數字的個數,在下面演示的示例中通過操作quantity來更新資料庫的資訊,另外的version欄位是資料庫資訊的版本號,能通過校驗來實現控制資料庫的操作,它的具體控制方法要在對映檔案中編寫實現。

package com.src.hibernate;

public class inventory

public void setitemno(string itemno)

//列表名稱

private string itemname;

public string getitemname()

public void setitemname(string itemname)

//個數

private int quantity;

public int getquantity()

public void setquantity(int quantity)

//版本號

private int version;

public int getversion()

public void setversion(int version)

}

在對映檔案中需要新增欄位來實現對資料庫版本號的對映,該標籤的name屬性要設定為對應實體中的version欄位,這樣在運算元據庫時它會自動校驗資料庫版本號來限制對資料的操作。

<?xml version="1.0"?>

測試上面的示例,在程式中新增了兩個方法來載入並修改資料,其中的testload1()方法首先載入資料庫中的資料,並修改欄位quantity的值,修改後儲存資料,這時要設定斷點,在提交事務時設定斷點,停止對資料庫的提交操作,此時執行testload2()方法,將會發出錯誤資訊,不能更新資料庫操作。

public void testload1()catch(exception e)finally

}public void testload2()catch(exception e)finally

}

在不停止testload1()方法時執行testload2()方法,hibernate發出如下語句,該語句說明testload2已經修改了資料庫中的資料,但是testload1也在修改只是沒有提交。

hibernate: select inventory0_.itemno as itemno0_0_, inventory0_.version as version0_0_, inventory0_.itemname as itemname0_0_, inventory0_.quantity as quantity0_0_ from t_inventory inventory0_ where inventory0_.itemno=?

p2-->name:zhangsan

hibernate: update t_inventory set version=?, itemname=?, quantity=? where itemno=? and version=?

testload2()提交更改後,接下來執行testload1()的斷點,將會發出:

的錯誤,說明兩個同時在修改同一條資料,導致了併發操作,發出了錯誤提示。

悲觀鎖和樂觀鎖不同,它是通過資料庫機制限制對資料庫的操作的,通過使用方法的lockmode引數來配置對資料庫的併發操作,在一次訪問過程中將會把資料鎖住(查詢時),只要事務不提交那麼任何使用者都不能檢視和修改,其它使用者操作時將會被阻塞,不能同時操作,需要等待第一次訪問完成後再進行其它的操作。具體方法如下示例。

實體內容和樂觀鎖相同,不同的是在實體中不需要新增版本號屬性,因為它不是通過判斷版本號來限制操作的。

package com.src.hibernate;

public class inventory

public void setitemno(string itemno)

//列表名稱

private string itemname;

public string getitemname()

public void setitemname(string itemname)

//個數

private int quantity;

public int getquantity()

public void setquantity(int quantity)

}

實體對應的對映檔案也相當的簡單,只需要配置相應的對映即可,沒有其它複雜的操作,如下**:

<?xml version="1.0"?>

這裡採用兩個方法來測試操作,其中的testload1()方法首先查詢資料然後修改資料,testload2()也是查詢和修改資料,如下**:

public void testload1()catch(exception e)finally

}public void testload2()catch(exception e)finally

}

演示併發操作時在testload1()方法的列印處設定相應的斷點,然後啟動debug除錯,執行到斷點後停止,此時執行testload2()方法,實現了對資料庫的併發操作,在執行testload2()方法時hibernate發出了sql語句,但是卻一直不能查詢和檢索資料,因為資料庫中加了悲觀鎖,資料庫限制了併發性的操作,所以hibernate只是發出了命令但是一直沒有操作許可權,也就是說testload2()方法在執行時遭到了阻塞,操作被壓到堆疊中等待上次的完成。當testload1()方法執行完後,將會從堆疊中繼續獲取testload2()的操作命令,這種樂觀鎖不僅限制了對資料的操作而且還能保證資料的完整性。

hibernate的鎖機制限制了資料庫的併發性的操作,功能很強大,在使用時建議使用悲觀鎖,因為悲觀鎖使用的是資料庫的機制,限制徹底,而且能確保資料的完整性。在使用這兩種鎖時各有優缺點,大資料量建議採用樂觀鎖,它會直接提示錯誤,效能上會高於悲觀鎖,悲觀鎖會加大資料庫的負擔,大資料量的話容易出現問題。

Hibernate步步為營 對映合集彙總

前幾篇文章具體討論了物件模型到關係模型的轉化方法,對對映關係做了具體的了解,hibernate將物件模型轉化為對應的關係模型是通過使用對應的對映來完畢的 相同也能夠使用註解 對於物件之間的關係的轉化則是通過使用對應的標籤來實現的,物件模型的關係多樣性,決定了關係模型的多樣性,本文將會對關係對映做總結...

步步為營 79 快取

快取cache,一種空間換取時間的技術,適用於經常訪問,不常修改的資料.1 寫入快取 1.1 方法一 cache message ab 1.2 方法二 cache.insert message ab 1.3 其他過載 insert string key,object value,cachedepen...

步步為營 50 事務

說明 比較常用 1 事務的四大特性 1.1 原子性atomicity 乙個事務中包含的多個sql語句,要麼同時成功,要麼同時失敗.1.2 一致性consistency 事務必須使資料庫從從乙個一致性狀態變成另外乙個一致性狀態.銀行轉賬 1.3 隔離性 isolation 各個事務執行互不干擾 鎖 1...